/** 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 #include #include #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; byte *ScrBuf; typedef struct { byte *rom[8]; byte huge *ram; } ti85memory; ti85memory memory; byte PCto85KeyMap[256-32] = {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,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,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 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 return CurrentKey; case 2: return (DisplayContrast & 0x1f); case 3: return 0xc; case 5: return CurrentRom; case 6: return PowerReg; case 7: return 0x0F; 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 huge byte[65536L])==NULL) { printf("big pag in the memory department!!..."); return(0); } for (longCount=0;longCount<65536L;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) { ReadKeypad(); DrawScreen(); } void ReadKeypad(void) { char key; if(kbhit()) { key=getch(); if (key=='#') TI85Exit(); CurrentKey=PCto85KeyMap[key]; } } 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