/** TI85: TI85 EMulator ***********************************/ /** **/ /** TI85.CPP **/ /** **/ /** This file contains implementation for the TI85-specific **/ /** hardware: Rom mapper, i/o ports etc **/ /** 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. **/ /** Modifications to MSX.C Copyright (C) Robert Taylor 1995.**/ /** **/ /*************************************************************/ #include "TI85.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <io.h> #include <sys\stat.h> #include <fcntl.h> #include <share.h> #include <dos.h> #include <conio.h> #include <alloc.h> #include "wgtgfx.h" /***************************************************************/ /** The z80 emulator performs it's operations on a continuous **/ /** block of memory (Called memory.ram). The ROM pages are **/ /** stored separately in an array memory.rom[]. **/ /***************************************************************/ int Verbose; byte CurrentRom=1; byte CurrentKey=0; byte KeypadMask=0; byte PowerReg=0; byte DisplayContrast=0; byte LinkReg=0x0F; int IntCount=0; int KeyPressed=0; byte *ScrBuf; typedef struct { byte *rom[8]; byte *ram; } ti85memory; ti85memory memory; byte RealKeyMap[8] = {0x7f,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf }; byte PCto85KeyMap[256] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0F,0x20,0x00,0x00,0x00,0x09,0x00,0x00, 0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x00, 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x1d,0x15,0x0c,0x0a,0x2b,0x0b,0x19,0x0d, 0x21,0x22,0x1a,0x12,0x23,0x1b,0x13,0x24, 0x1c,0x14,0x00,0x00,0x00,0x2a,0x00,0x00, 0x00,0x00,0x00,0x17,0x00,0x37,0x00,0x2F, 0x04,0x00,0x00,0x02,0x00,0x03,0x00,0x38, 0x01,0x00,0x1F,0x27,0x00,0x00,0x00,0x00, 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x2e,0x26,0x1e,0x16,0x0e,0x2d,0x25, 0x1d,0x15,0x0d,0x2c,0x24,0x1c,0x14,0x0c, 0x2b,0x23,0x1b,0x13,0x0b,0x22,0x1a,0x12, 0x0a,0x21,0x19,0x00,0x00,0x00,0x00,0x20, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; byte PCEto85KeyMap[256] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x35,0x34,0x33,0x32,0x31, 0x00,0x00,0x00,0x36,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; /****************************************************************/ /*** Write number into given IO port. ***/ /****************************************************************/ void DoOut(register byte Port,register byte Value) { switch(Port) { case 1: KeypadMask=Value; break; case 2: DisplayContrast=Value; case 5: MapROM(Value); break; case 6: PowerReg=Value; break; case 7: LinkReg=(LinkReg & 0xF3) | (Value & 0xC); break; } } /****************************************************************/ /*** Read number from given IO port. ***/ /****************************************************************/ byte DoIn(register byte Port) { switch(Port) { case 1: //Keypad if ((KeypadMask&1) && (CurrentKey<8)) { return 0xff; } if ((KeypadMask&2) && (CurrentKey<16) && (CurrentKey>8)) { return 0xff; } if ((KeypadMask&4) && (CurrentKey<24) && (CurrentKey>16)) { return 0xff; } if ((KeypadMask&8) && (CurrentKey<33) && (CurrentKey>24)) { return 0xff; } if ((KeypadMask&16) && (CurrentKey<41) && (CurrentKey>32)) { return 0xff; } if ((KeypadMask&32) && (CurrentKey<49) && (CurrentKey>41)) { return 0xff; } if ((KeypadMask&64) && (CurrentKey<57) && (CurrentKey>48)) { return 0xff; } //printf("%x",CurrentKey); if (CurrentKey) { return RealKeyMap[CurrentKey&7]; } else { return 0xff; } case 2: printf("changed contrast"); return (DisplayContrast & 0x1f); case 3: { return 0xa; } case 5: return CurrentRom; case 6: return PowerReg; case 7: return LinkReg; default: return 0xFF; } } /****************************************************************/ /*** Switch ROM pages: this routine copys the data from the ***/ /*** relavent ROM into the mapped ROM space (0x4000-0x7fff) ***/ /****************************************************************/ void MapROM(register byte NewRom) { word Count; NewRom &=7; if (!(CurrentRom==NewRom) ) { CurrentRom=NewRom; for (Count=0;Count<0x4000;Count++) { memory.ram[Count+0x4000]=memory.rom[NewRom][Count]; } } } /****************************************************************/ /*** Allocate memory, load ROM images, initialize screen, ***/ /*** CPU and start the emulation. This function returns 0 in ***/ /*** the case of failure. ***/ /****************************************************************/ int StartTI85(void) { word A; reg R; int *T; word Count; int RomNo; long longCount; T=(int *)"\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; #ifdef LSB_FIRST if(*T!=1) { printf("********** This machine is high-endian. **********\n"); printf("Take #define LSB_FIRST out and compile Em85 again.\n"); return(0); } #else if(*T==1) { printf("********* This machine is low-endian. **********\n"); printf("Insert #define LSB_FIRST and compile Em85 again.\n"); return(0); } #endif InitScreen(); if(!(ScrBuf=new byte[320*200])) { printf("couldnt allcode screen mem"); return(0); } memset(ScrBuf,0,320*199); for(RomNo=0;RomNo<8;RomNo++) { if((memory.rom[RomNo]=new byte[16384])==NULL) { printf("big pag in the memory department!!..."); return(0); } } if((memory.ram=new byte[65535U])==NULL) { printf("big pag in the memory department!!..."); return(0); } for (longCount=0;longCount<65535L;longCount++) { memory.ram[longCount]=0; } if(Verbose) printf("OK\nLoading TI85 ROM:\n"); LoadROM("ti85rom.bin"); // fd 21 46 83 memory.rom[0][0xd01]=0xCD; // fix the rom so it clears the memory.rom[0][0xd02]=0x15; // memory first... memory.rom[0][0xd03]=0x0b; memory.rom[0][0xd04]=0x00; for (Count=0;Count<0x4000;Count++) { memory.ram[Count]=memory.rom[0][Count]; } for (Count=0;Count<0x4000;Count++) { memory.ram[Count+0x4000]=memory.rom[1][Count]; } R.PC.W=0;R.SP.W=0xF000;R.IFF=0; if(Verbose) printf("OK\nRUNNING ROM CODE...\n"); A=Z80(memory.ram,R); if(Verbose) printf("EXITED at PC = %Xh.\n",A); return(1); } /****************************************************************/ /*** Free memory allocated with StartTI85(). ***/ /****************************************************************/ void TrashTI85(void) { int RomNo; delete ScrBuf; delete memory.ram; for (RomNo=0;RomNo<8;RomNo++) { delete memory.rom[RomNo]; } if (Verbose) printf("Exiting"); } /*Main routines*/ int main(void) { Verbose=1; StartTI85(); TrashTI85(); return 0; } void TI85Exit(void) { TrashTI85(); exit(1); } /****************************************************************/ /*** Load the ROM image into the ROM store **/ /****************************************************************/ void LoadROM(char *filename) { int RomNo; int handle; if ((handle = open(filename, O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1) { printf("Error Opening File\n"); exit(1); } for(RomNo=0;RomNo<8;RomNo++) { if ((_read(handle, memory.rom[RomNo], 0x4000)) == -1) { printf("Read Failed.\n"); exit(1); } } } /****************************************************************/ /*** Set sound parameters, refresh screen, check keyboard and ***/ /*** sprites. Call this function on each interrupt. ***/ /****************************************************************/ void Interrupt(void) { if ((++IntCount)>=5) { ReadKeypad(); DrawScreen(); } } void ReadKeypad(void) { int key; if(kbhit()) { key=getch(); if (key) { if (key=='#') TI85Exit(); CurrentKey=PCto85KeyMap[(unsigned char) key]; KeyPressed=1; } else { key=getch(); CurrentKey=PCEto85KeyMap[(unsigned char) key]; KeyPressed=1; } // printf("%x",CurrentKey); } else { KeyPressed=0; } } void DrawScreen(void) { int x,y,bit; for(y=0;y<64;y++) for(x=0;x<16;x++) for(bit=0;bit<8;bit++) ScrBuf[(y*320)+(x<<3)+bit]=(memory.ram[0xFC00U+(y<<4)+x] >> (7-bit))&1; memcpy(abuf,ScrBuf,320*64); } void InitScreen(void) { setvga256(); } void MemCopy(byte *Dest, byte *Source,long Size) { long Count; for (Count=0;Count<Size;Count++) { *(Dest++)=*(Source++); } }