/** fMSX: portable MSX emulator ******************************/ /** **/ /** MSX.c **/ /** **/ /** This file contains implementation for the MSX-specific **/ /** hardware: slots, memory mapper, PPIs, VDP, PSG, clock, **/ /** etc. Initialization code and definitions needed for the **/ /** machine-dependent drivers are also here. **/ /** **/ /** 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 "TI85.h" #include #include #include #include #include #include #include #include #include #include "wgtgfx.h" #define PutImage \ memcpy((char *)0xA0000,(char *)XBuf+WIDTH*(HEIGHT-200)/2,320*200) #define DRIVERNAME "320X200.DRV" int Verbose; byte *RAM; byte *ROMMap= {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; /* Blocks for ROM Mappers */ byte CurrentRom=1; byte CurrentKey=0; byte KeypadMask=0; byte PowerReg=0x0; byte DisplayContrast=0; byte LinkReg=0x0F; byte *ScrBuf; 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 LinkReg; default: return 0xFF; } } /****************************************************************/ /*** Switch ROM Mapper pages. This function is supposed to be ***/ /*** to be called when ROM page registers are written to. ***/ /****************************************************************/ void MapROM(register byte NewRom) { byte *ptr; NewRom &=7; if (!(CurrentRom==NewRom) ) { CurrentRom=NewRom; MemCopy(RAM+0x4000,ROMMap[NewRom],PAGESIZE); } } /****************************************************************/ /*** Allocate memory, load ROM images, initialize mapper, VDP ***/ /*** CPU and start the emulation. This function returns 0 in ***/ /*** the case of failure. ***/ /****************************************************************/ int StartTI85(void) { word A; reg R; int *T,J; 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); if(Verbose) printf("Allocating 64kB for address space..."); if(!(RAM=new byte[4*PAGESIZE])) return(0); if(Verbose) printf("OK\nAllocating 8x16kB ROM pages..."); for (J=0;J<8;J++) { if(!(ROMMap[J]=new byte[PAGESIZE])) { printf("Error allocating ROM blocks"); return(0); } } if(Verbose) printf("OK\nLoading TI85 ROM:\n"); LoadROM("ti85rom.bin"); // fd 21 46 83 ROMMap[0][0xd01]=0xCD; ROMMap[0][0xd02]=0x15; ROMMap[0][0xd03]=0x0b; ROMMap[0][0xd04]=0x00; MemCopy(RAM,ROMMap[0],PAGESIZE); MemCopy(RAM+0x4000,ROMMap[1],PAGESIZE); memset(RAM+0x8000,0,2*PAGESIZE); R.PC.W=0;R.SP.W=0xF000;R.IFF=0; if(Verbose) printf("OK\nRUNNING ROM CODE...\n"); A=Z80(RAM,R); if(Verbose) printf("EXITED at PC = %Xh.\n",A); return(1); } /****************************************************************/ /*** Free memory allocated with StartMSX(). ***/ /****************************************************************/ void TrashTI85(void) { byte I; union REGS R; delete ScrBuf; delete RAM; delete[] ROMMap; if (Verbose) printf("Exiting"); } /*Main routines*/ int main(void) { Verbose=1; StartTI85(); TrashTI85(); return 0; } void TI85Exit(void) { TrashTI85(); exit(1); } /****************************************************************/ /*** Load a ROM page from the file F into slot P, subslot S, ***/ /*** page A. Return memory address of a page or 0 if failed. ***/ /****************************************************************/ 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, ROMMap[RomNo], PAGESIZE)) == -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,cpy; for(y=0;y<64;y++) for(x=0;x<16;x++) for(bit=0;bit<8;bit++) ScrBuf[(y*320)+(x<<3)+bit]=(RAM[0xFc00+(y<<4)+x] >> (7-bit))&1; memcpy(abuf,ScrBuf,320*64); } void InitScreen(void) { setvga256(); } void MemCopy(byte *Dest, byte *Source,unsigned int Size) { long Count; for (Count=0;Count