/** fMSX: portable MSX emulator ******************************/ /** **/ /** Lame.h **/ /** **/ /** This file contains simplified version of Z80 emulation **/ /** which can be used if your compiler can't handle the **/ /** original version. Simplified code is going to be **/ /** slightly slower, although optimization may improve its **/ /** perfomance. In this version, M_WRMEM() is implemented **/ /** as a function [instead of a macro] and each subset of **/ /** Z80 commands is also made into a separate function **/ /** called when appropriate prefix appears. **/ /** **/ /** Copyright (C) Marat Fayzullin 1994,1995 **/ /** You are not allowed to distribute this software **/ /** commercially. Please, notify me, if you make any **/ /** changes to this file. **/ /*************************************************************/ #include //#include #include reg R; byte *Addr; byte FLAG; #ifdef INTERRUPTS word Cnt; #endif inline void M_WRMEM(register word A,register byte V) { // if (!(A&0x8000)) // { cprintf("wrote to rom, %x,%x",A,R.PC.W); TI85Exit();} // else {*(Addr+A)=V;} } void CodesCBf(void) { register byte I; switch(*(Addr+(R.PC.W++))) { #include "CodesCB.h" default: printf("Unrecognized CB instruction at PC=%hX\n",R.PC.W-=2); FLAG=0; } } void CodesDDCB(register pair J) { register byte I; #define XX IX switch(*(Addr+long(R.PC.W++))) { #include "CodesXCB.h" default: printf("Unrecognized DD CB instruction at PC=%hX\n",R.PC.W-=3); FLAG=0; } #undef XX } void CodesFDCB(register pair J) { register byte I; #define XX IY switch(*(Addr+(R.PC.W++))) { #include "CodesXCB.h" default: printf("Unrecognized FD CB instruction at PC=%hX\n",R.PC.W-=3); FLAG=0; } #undef XX } void CodesEDf(void) { register byte I; register pair J; switch(*(Addr+(R.PC.W++))) { #include "CodesED.h" default: printf("Unrecognized ED instruction at PC=%hX\n",R.PC.W-=2); FLAG=0; } } void CodesDD(void) { register byte I; register pair J; #define XX IX switch(*(Addr+(R.PC.W++))) { #include "CodesXX.h" case PFX_FD: case PFX_DD: R.PC.W--;break; case PFX_CB: J.W=R.XX.W+(*(char *)(Addr+(R.PC.W++))); CodesDDCB(J);break; case HALT: #ifdef INTERRUPTS if(R.IFF&1) { if(Cnt) R.PC.W--; } else #endif { printf("CPU HALTed and stuck at PC=%hX\n",R.PC.W-=2); FLAG=0; } break; default: printf("Unrecognized DD instruction at PC=%hX\n",R.PC.W-=2); FLAG=0; } #undef XX } void CodesFD(void) { register byte I; register pair J; #define XX IY switch(*(Addr+(R.PC.W++))) { #include "CodesXX.h" case PFX_FD: case PFX_DD: R.PC.W--;break; case PFX_CB: J.W=R.XX.W+(*(char *)(Addr+(R.PC.W++))); CodesFDCB(J);break; case HALT: #ifdef INTERRUPTS if(R.IFF&1) { if(Cnt) R.PC.W--; } else #endif { printf("CPU HALTed and stuck at PC=%hX\n",R.PC.W-=2); FLAG=0; } break; default: printf("Unrecognized FD instruction at PC=%hX\n",R.PC.W-=2); FLAG=0; } #undef XX } word Z80(register byte *A,reg Regs) { register byte I; register pair J; R=Regs;Addr=A; clock_t start; start=clock(); #ifdef INTERRUPTS Cnt=IPeriod; #endif for(FLAG=1;FLAG;) { switch(*(Addr+(R.PC.W++))) { #include "Codes.h" case PFX_CB: CodesCBf();break; case PFX_ED: CodesEDf();break; case PFX_FD: CodesFD();break; case PFX_DD: CodesDD();break; case HALT: #ifdef INTERRUPTS if(R.IFF&1) { if(Cnt) R.PC.W--; } else #endif { //printf("CPU HALTed and stuck at PC=%hX\n",--R.PC.W); // FLAG=0; } break; default: printf("Unrecognized instruction at PC=%hX\n",--R.PC.W); FLAG=0; } #ifdef INTERRUPTS if(!Cnt--) { Cnt=IPeriod; if(IntSync) IFlag=1; // printf("time for 10000 instructions = %f",(clock()-start)/CLK_TCK); // start=clock(); } if(IFlag) { IFlag=0;Interrupt(); if(R.IFF&1) { M_PUSH(PC);R.PC.W=0x0038; } } #endif #ifdef DEBUG if(R.PC.W==Trap) Trace=1; /*** Turn tracing on if trapped ***/ if(Trace) Debug(Addr,R); /*** Call single-step debugger ***/ #endif } return(R.PC.W); }