/** 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 #include #include #include #include #include #include #include //#include #define MemCopy(x,y,z) memcpy(x,y,z) /***************************************************************/ /** 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; char far *Screen = (char far*) MK_FP(0xA000,0); 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, 0x04,0x00,0x00,0x02,0x00,0x03,0x00,0x00, 0x01,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,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; } if (CurrentKey) { return RealKeyMap[CurrentKey&7]; } else { return 0xff; } case 2: cprintf("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) { if(CurrentRom==NewRom) return; word Count; NewRom &=7; CurrentRom=NewRom; memcpy(memory.ram+0x4000,memory.rom[NewRom],0x4000); } /****************************************************************/ /*** 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) { cprintf("********** This machine is high-endian. **********\n"); cprintf("Take #define LSB_FIRST out and compile Em85 again.\n"); return(0); } #else if(*T==1) { cprintf("********* This machine is low-endian. **********\n"); cprintf("Insert #define LSB_FIRST and compile Em85 again.\n"); return(0); } #endif InitScreen(); // if(!(ScrBuf=new byte[320*200])) { // cprintf("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) { cprintf("big pag in the memory department!!..."); return(0); } } if((memory.ram=new byte[65535U])==NULL) { cprintf("big pag in the memory department!!..."); return(0); } memset(memory.ram,0,65535L); if(Verbose) cprintf("OK \r\n Loading TI-85 ROM:\r\n"); LoadROM("ti85rom.bin"); memcpy(memory.ram,memory.rom[0],0x4000); memcpy(memory.ram+0x4000,memory.rom[1],0x4000); // fd 21 46 83 memory.ram[0xd01]=0xCD; // fix the rom so it clears the memory.ram[0xd02]=0x15; // memory first... memory.ram[0xd03]=0x0b; memory.ram[0xd04]=0x00; R.PC.W=0;R.SP.W=0xF000;R.IFF=0; if(Verbose) cprintf("OK \r\n Running ROM code...\r\n"); A=Z80(memory.ram,R); if(Verbose) cprintf("Exited at PC = %Xh.\r\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) cprintf("Exiting\r\n"); asm { mov ax,3 int 10h } cprintf(" TI-85 Emulator, v1.0à\r\n" "\r\n" " by Robert Taylor\r\n" " original code by Marat Fayzullin\r\n" " optimizations by Ilya Haykinson\r\n"); } /*Main routines*/ int main(void) { Verbose=0; 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) { cprintf("Error Opening File\r\n"); exit(1); } for(RomNo=0;RomNo<8;RomNo++) { if ((_read(handle, memory.rom[RomNo], 0x4000)) == -1) { printf("Read Failed.\r\n"); exit(1); } } } /*********************************************/ /*** Refresh screen and check keyboard ***/ /*** Call this function on each interrupt. ***/ /*********************************************/ void Interrupt(void) { if ((++IntCount)>=4) { ReadKeypad(); DrawScreen(); IntCount=0; } } void ReadKeypad(void) { int key; if(kbhit()) { key=getch(); if (key) { if (key==0x1b) TI85Exit(); CurrentKey=PCto85KeyMap[(unsigned char) key]; KeyPressed=1; } else { key=getch(); CurrentKey=PCEto85KeyMap[(unsigned char) key]; KeyPressed=1; } } else { KeyPressed=0; CurrentKey=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++) Screen[(y<<8)+(y<<6)+(x<<3)+bit]=(memory.ram[0xFC00U+(y<<4)+x] >> (7-bit))&1; } void InitScreen(void) { asm { mov ax,13h int 10h } memset(Screen,0,64000U); }