/* * mops.c * * This file is part of Emu48 * * Copyright (C) 1995 Sebastien Carlier * */ #include "pch.h" #include "Emu48.h" #define SXCONFIG 1 // CRC calculation static WORD crc_table[16] = { 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387, 0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F }; static __inline VOID CRC(BYTE nib) { Chipset.crc = (WORD)((Chipset.crc>>4)^crc_table[(Chipset.crc^nib)&0xf]); } LPBYTE RMap[256] = {NULL,}; LPBYTE WMap[256] = {NULL,}; static __inline UINT MIN(UINT a, UINT b) { return (ab)?a:b; } static VOID MapP0(BYTE a, BYTE b) { UINT i; DWORD p, m; a = (BYTE)MAX(a,Chipset.P0Base); b = (BYTE)MIN(b,Chipset.P0End); m = (Chipset.Port0Size*2048)-1; p = ((a-Chipset.P0Base)<<12)&m; for (i=a; i<=b; i++) { RMap[i]=Chipset.Port0 + p; WMap[i]=Chipset.Port0 + p; p = (p+0x1000)&m; } return; } static VOID MapBS(BYTE a, BYTE b) { UINT i; DWORD p, m; a = (BYTE)MAX(a,Chipset.BSBase); b = (BYTE)MIN(b,Chipset.BSEnd); m = (dwRomSize-1)&0xFF000; p = a*0x1000; for (i=a;i<=b;i++) { RMap[i]=pbyRom + p; WMap[i]=NULL; p = (p+0x1000)&m; } return; } static VOID MapP1(BYTE a, BYTE b) { UINT i; DWORD p, m; if (Chipset.Port1 == NULL) return; a = (BYTE)MAX(a,Chipset.P1Base); b = (BYTE)MIN(b,Chipset.P1End); m = (Chipset.Port1Size*2048)-1; p = ((a-Chipset.P1Base)<<12)&m; if (Chipset.Port1_Writeable) { for (i=a; i<=b; i++) { RMap[i]=Chipset.Port1 + p; WMap[i]=Chipset.Port1 + p; p = (p+0x1000)&m; } } else { for (i=a; i<=b; i++) { RMap[i]=Chipset.Port1 + p; WMap[i]=NULL; p = (p+0x1000)&m; } } return; } static VOID MapP2(BYTE a, BYTE b) { UINT i; DWORD p, m; LPBYTE pbyTemp; if (pbyPort2 == NULL) return; pbyTemp = pbyPort2 + (nPort2Bank << 18); a = (BYTE)MAX(a,Chipset.P2Base); b = (BYTE)MIN(b,Chipset.P2End); m = (Chipset.Port2Size*2048)-1; p = ((a-Chipset.P2Base)<<12)&m; if (bPort2Writeable) { for (i=a; i<=b; i++) { RMap[i]=pbyTemp + p; WMap[i]=pbyTemp + p; p = (p+0x1000)&m; } } else { for (i=a; i<=b; i++) { RMap[i]=pbyTemp + p; WMap[i]=NULL; p = (p+0x1000)&m; } } return; } static VOID MapROM(BYTE a, BYTE b) { UINT i; DWORD p, m; m = (dwRomSize-1)&0xFF000; p = a*0x1000; for (i=a;i<=b;i++) { RMap[i]=pbyRom + p; WMap[i]=NULL; p = (p+0x1000)&m; } return; } VOID Map(BYTE a, BYTE b) { #if SXCONFIG if (cCurrentRomType=='S') { MapROM(a,b); if (Chipset.BSCfig) MapBS(a,b); if (Chipset.P2Cfig) MapP2(a,b); if (Chipset.P1Cfig) MapP1(a,b); if (Chipset.P0Cfig) MapP0(a,b); return; } #endif MapROM(a,b); if (Chipset.P2Cfig) MapP2(a,b); if (Chipset.P1Cfig) MapP1(a,b); if (Chipset.BSCfig) MapBS(a,b); if (Chipset.P0Cfig) MapP0(a,b); return; } //////////////////////////////////////////////////////////////////////////////// // // Bus Commands // //////////////////////////////////////////////////////////////////////////////// VOID Config() { DWORD d = Npack(Chipset.C,5); BYTE b = (BYTE)(d>>12); BYTE s = (BYTE)(b^0xFF); #if SXCONFIG if (cCurrentRomType=='S') { if (!Chipset.IOCfig) { Chipset.IOCfig=TRUE; Chipset.IOBase=d&0xFFFC0; Map(b,b); return; } if (!Chipset.P0Cfg2) { Chipset.P0Cfg2=TRUE; Chipset.P0Size=s; return; } if (!Chipset.P0Cfig) { Chipset.P0Cfig = TRUE; Chipset.P0Base = (BYTE)b; Chipset.P0End = (BYTE)(b+Chipset.P0Size); Map(Chipset.P0Base,Chipset.P0End); return; } if (!Chipset.P1Cfg2) { Chipset.P1Cfg2 = TRUE; Chipset.P1Size = (BYTE)s; return; } if (!Chipset.P1Cfig) { Chipset.P1Cfig = TRUE; Chipset.P1Base = (BYTE)b; Chipset.P1End = (BYTE)(b+Chipset.P1Size); Map(Chipset.P1Base,Chipset.P1End); return; } if (!Chipset.P2Cfg2) { Chipset.P2Cfg2 = TRUE; Chipset.P2Size = (BYTE)s; return; } if (!Chipset.P2Cfig) { Chipset.P2Cfig = TRUE; Chipset.P2Base = (BYTE)b; Chipset.P2End = (BYTE)(b+Chipset.P2Size); Map(Chipset.P2Base,Chipset.P2End); return; } if (!Chipset.BSCfg2) { Chipset.BSCfg2=TRUE; Chipset.BSSize=s; return; } if (!Chipset.BSCfig) { Chipset.BSCfig = TRUE; Chipset.BSBase = (BYTE)b; Chipset.BSEnd = (BYTE)(b+Chipset.BSSize); Map(Chipset.BSBase,Chipset.BSEnd); return; } return; } #endif if (!Chipset.IOCfig) { Chipset.IOCfig=TRUE; Chipset.IOBase=d&0xFFFC0; Map(b,b); return; } if (!Chipset.P0Cfg2) { Chipset.P0Cfg2=TRUE; Chipset.P0Size=s; return; } if (!Chipset.P0Cfig) { Chipset.P0Cfig = TRUE; Chipset.P0Base = (BYTE)b; Chipset.P0End = (BYTE)(b+Chipset.P0Size); Map(Chipset.P0Base,Chipset.P0End); return; } if (!Chipset.BSCfg2) { Chipset.BSCfg2=TRUE; Chipset.BSSize=s; return; } if (!Chipset.BSCfig) { Chipset.BSCfig = TRUE; Chipset.BSBase = (BYTE)b; Chipset.BSEnd = (BYTE)(b+Chipset.BSSize); Map(Chipset.BSBase,Chipset.BSEnd); return; } if (!Chipset.P1Cfg2) { Chipset.P1Cfg2 = TRUE; Chipset.P1Size = (BYTE)s; return; } if (!Chipset.P1Cfig) { Chipset.P1Cfig = TRUE; Chipset.P1Base = (BYTE)b; Chipset.P1End = (BYTE)(b+Chipset.P1Size); Map(Chipset.P1Base,Chipset.P1End); return; } if (!Chipset.P2Cfg2) { Chipset.P2Cfg2 = TRUE; Chipset.P2Size = (BYTE)s; return; } if (!Chipset.P2Cfig) { Chipset.P2Cfig = TRUE; Chipset.P2Base = (BYTE)b; Chipset.P2End = (BYTE)(b+Chipset.P2Size); Map(Chipset.P2Base,Chipset.P2End); return; } return; } VOID Uncnfg() { DWORD d=Npack(Chipset.C,5); BYTE b=(BYTE)(d>>12); #if SXCONFIG if (cCurrentRomType=='S') { if ((Chipset.IOCfig)&&(d==Chipset.IOBase)) {Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000;Map(b,b);return;} if ((Chipset.P0Cfig)&&(b==Chipset.P0Base)) {Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Map(Chipset.P0Base,Chipset.P0End);return;} if ((Chipset.P1Cfig)&&(b==Chipset.P1Base)) {Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(Chipset.P1Base,Chipset.P1End);return;} if ((Chipset.P2Cfig)&&(b==Chipset.P2Base)) {Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(Chipset.P2Base,Chipset.P2End);return;} if ((Chipset.BSCfig)&&(b==Chipset.BSBase)) {Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(Chipset.BSBase,Chipset.BSEnd);return;} return; } #endif if ((Chipset.IOCfig)&&(d==Chipset.IOBase)) {Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000;Map(b,b);return;} if ((Chipset.P0Cfig)&&(b==Chipset.P0Base)) {Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Map(Chipset.P0Base,Chipset.P0End);return;} if ((Chipset.BSCfig)&&(b==Chipset.BSBase)) {Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(Chipset.BSBase,Chipset.BSEnd);return;} if ((Chipset.P1Cfig)&&(b==Chipset.P1Base)) {Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(Chipset.P1Base,Chipset.P1End);return;} if ((Chipset.P2Cfig)&&(b==Chipset.P2Base)) {Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(Chipset.P2Base,Chipset.P2End);return;} return; } VOID Reset() { Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000; Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Chipset.P0Base=0;Chipset.P0Size=0;Chipset.P0End=0; Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Chipset.BSBase=0;Chipset.BSSize=0;Chipset.BSEnd=0; Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Chipset.P1Base=0;Chipset.P1Size=0;Chipset.P1End=0; Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Chipset.P2Base=0;Chipset.P2Size=0;Chipset.P2End=0; Map(0x00,0xFF); return; } VOID C_Eq_Id() { #if SXCONFIG if (cCurrentRomType=='S') { if (!Chipset.IOCfig) {Nunpack(Chipset.C,(Chipset.IOBase*0x1000)^0x00019,5);return;} if (!Chipset.P0Cfg2) {Nunpack(Chipset.C,(Chipset.P0Size*0x1000)^0xFF003,5);return;} if (!Chipset.P0Cfig) {Nunpack(Chipset.C,(Chipset.P0Base*0x1000)^0x000F4,5);return;} if (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF005,5);return;} if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F6,5);return;} if (!Chipset.P2Cfg2) {Nunpack(Chipset.C,(Chipset.P2Size*0x1000)^0xFF007,5);return;} if (!Chipset.P2Cfig) {Nunpack(Chipset.C,(Chipset.P2Base*0x1000)^0x000F8,5);return;} if (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF001,5);return;} if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F2,5);return;} memset(Chipset.C,0,5); return; } #endif if (!Chipset.IOCfig) {Nunpack(Chipset.C,(Chipset.IOBase*0x1000)^0x00019,5);return;} if (!Chipset.P0Cfg2) {Nunpack(Chipset.C,(Chipset.P0Size*0x1000)^0xFF003,5);return;} if (!Chipset.P0Cfig) {Nunpack(Chipset.C,(Chipset.P0Base*0x1000)^0x000F4,5);return;} if (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF005,5);return;} if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F6,5);return;} if (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF007,5);return;} if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F8,5);return;} if (!Chipset.P2Cfg2) {Nunpack(Chipset.C,(Chipset.P2Size*0x1000)^0xFF001,5);return;} if (!Chipset.P2Cfig) {Nunpack(Chipset.C,(Chipset.P2Base*0x1000)^0x000F2,5);return;} memset(Chipset.C,0,5); return; } VOID Npeek(BYTE *a, DWORD d, UINT s) { DWORD u, v; UINT c; BYTE *p; do { u = d>>12; v = d&0xFFF; c = MIN(s,0x1000-v); if ((p=RMap[u]) != NULL) memcpy(a, p+v, c); if (s-=c) {a+=c; d+=c;} } while (s); return; } VOID Nread(BYTE *a, DWORD d, UINT s) { DWORD u, v; UINT c; BYTE *p; do { if ((d&0xFFFC0)==Chipset.IOBase) { v = d&0x3F; c = MIN(s,0x40-v); ReadIO(a,v,c); } else { u = d>>12; v = d&0xFFF; c = MIN(s,0x1000-v); if ((p=RMap[u]) != NULL) { memcpy(a, p+v, c); for (u=0; u=Chipset.start12)) WriteToMainDisplay(a,d,s); if ((d=Chipset.start2)) WriteToMenuDisplay(a,d,s); do { if ((d&0xFFFC0)==Chipset.IOBase) { v = d&0x3F; c = MIN(s,0x40-v); WriteIO(a, v, c); } else { u = d>>12; v = d&0xFFF; c = MIN(s,0x1000-v); if ((p=WMap[u]) != NULL) memcpy(p+v, a, c); } a+=c; d+=c; } while (s-=c); return; } VOID Nread2(BYTE *a, DWORD d) { DWORD u, v; BYTE *p; if ((d&0xFFFC0)==Chipset.IOBase) { u = d&0x3F; if (u>0x3E) {Nread(a,d,2);return;} ReadIO(a,u,2); return; } u = d>>12; v = d&0xFFF; if (u==Chipset.BSBase) // bank switching { nPort2Bank = (v&dwPort2Mask)>>1; Map(Chipset.P2Base,Chipset.P2End); a[0] = 3; a[1] = 3; return; } if (v>0xFFE) {Nread(a,d,2);return;} if ((p=RMap[u]) != NULL) { *((WORD*)a) = *((WORD*)(p+v)); CRC(a[0]); CRC(a[1]); } return; } VOID Nwrite2(BYTE *a, DWORD d) { DWORD u, v; BYTE *p; if ((d&0xFFFC0)==Chipset.IOBase) {Nwrite(a,d,2);return;} u = d>>12; v = d&0xFFF; if (v>0xFFE) {Nwrite(a,d,2);return;} if ((d=Chipset.start12)) WriteToMainDisplay(a,d,2); if ((d=Chipset.start2)) WriteToMenuDisplay(a,d,2); if ((p=WMap[u]) != NULL) { *((WORD*)(p+v)) = *((WORD*)a); } return; } VOID Nread5(BYTE *a, DWORD d) { DWORD u, v; BYTE *p; if ((d&0xFFFC0)==Chipset.IOBase) { u = d&0x3F; if (u>0x3A) {Nread(a,d,5);return;} ReadIO(a,u,5); return; } v = d&0xFFF; if (v>0xFFA) {Nread(a,d,5);return;} u = d>>12; if ((p=RMap[u]) != NULL) { *((DWORD*)a) = *((DWORD*)(p+v)); a[4] = p[v+4]; CRC(a[0]); CRC(a[1]); CRC(a[2]); CRC(a[3]); CRC(a[4]); } return; } VOID Nwrite5(BYTE *a, DWORD d) { DWORD u, v; BYTE *p; if ((d&0xFFFC0)==Chipset.IOBase) {Nwrite(a,d,5);return;} v = d&0xFFF; if (v>0xFFA) {Nwrite(a,d,5);return;} if ((d=Chipset.start12)) WriteToMainDisplay(a,d,5); if ((d=Chipset.start2)) WriteToMenuDisplay(a,d,5); u = d>>12; if ((p=WMap[u]) != NULL) { *((DWORD*)(p+v)) = *((DWORD*)a); p[v+4] = a[4]; } } DWORD Read5(DWORD d) { BYTE p[8]; Npeek(p,d,5); return Npack(p,5); } BYTE Read2(DWORD d) { BYTE p[2]; Npeek(p,d,2); return (BYTE)(p[0]|(p[1]<<4)); } VOID Write5(DWORD d, DWORD n) { BYTE p[8]; Nunpack(p,n,5); Nwrite(p,d,5); return; } VOID ReadIO(BYTE *a, DWORD b, DWORD s) { DWORD d = b; do { switch (d) { case 0x00: *a = (Chipset.dispon<<3)|Chipset.boffset; break; case 0x01: *a = Chipset.contrast&0xF; break; case 0x02: *a = Chipset.contrast>>4; break; case 0x03: *a = 0; case 0x04: *a = (Chipset.crc )&0xF; break; case 0x05: *a = (Chipset.crc>> 4)&0xF; break; case 0x06: *a = (Chipset.crc>> 8)&0xF; break; case 0x07: *a = (Chipset.crc>>12)&0xF; break; case 0x08: *a = 0; break; // case 0x09: *a = Chipset.IORam[0x09]; break; case 0x0A: *a = 0; break; // case 0x0B: *a = Chipset.IORam[0x0B]; break; // case 0x0C: *a = Chipset.IORam[0x0C]; break; // case 0x0D: *a = Chipset.IORam[0x0D]; break; // case 0x0E: *a = Chipset.IORam[0x0E]; break; case 0x0F: *a = Chipset.cards_status; break; // case 0x10: *a = Chipset.IORam[0x10]; break; // case 0x11: *a = Chipset.IORam[0x11]; break; case 0x12: *a = 0; break; case 0x13: *a = 0; break; case 0x14: *a = 0; Chipset.IORam[0x11]&=0xE; break; case 0x15: *a = 0; Chipset.IORam[0x11]&=0xE; break; case 0x16: *a = 0; break; case 0x17: *a = 0; break; // case 0x18: *a = Chipset.IORam[0x18]; break; // case 0x19: *a = Chipset.IORam[0x19]; break; case 0x1A: *a = 0; break; case 0x1B: *a = 0; break; case 0x1C: *a = 0; break; case 0x1D: *a = 0; break; // case 0x1E: *a = Chipset.IORam[0x1E]; break; // case 0x1F: *a = Chipset.IORam[0x1F]; break; case 0x20: *a = 3; break; case 0x21: *a = 3; break; case 0x22: *a = 3; break; case 0x23: *a = 3; break; case 0x24: *a = 3; break; case 0x25: *a = 3; break; case 0x26: *a = 3; break; case 0x27: *a = 3; break; case 0x28: if (Chipset.sync) Chipset.sync--; else Chipset.sync=Chipset.lcounter+1; *a = Chipset.sync&0xF; break; case 0x29: if (d==b) { if (Chipset.sync) Chipset.sync--; else Chipset.sync=Chipset.lcounter+1; } *a = Chipset.sync&0xF; break; case 0x2A: *a = 0; break; case 0x2B: *a = 0; break; case 0x2C: *a = 0; break; case 0x2D: *a = 0; break; // case 0x2E: *a = Chipset.IORam[0x2E]; break; // case 0x2F: *a = Chipset.IORam[0x2F]; break; case 0x30: *a = 3; break; case 0x31: *a = 3; break; case 0x32: *a = 3; break; case 0x33: *a = 3; break; case 0x34: *a = 3; break; case 0x35: *a = 0; break; case 0x36: *a = 0; break; case 0x37: *a = ReadT1(); break; case 0x38: Nunpack(a, ReadT2() , s); return; case 0x39: Nunpack(a, ReadT2()>> 4, s); return; case 0x3A: Nunpack(a, ReadT2()>> 8, s); return; case 0x3B: Nunpack(a, ReadT2()>>12, s); return; case 0x3C: Nunpack(a, ReadT2()>>16, s); return; case 0x3D: Nunpack(a, ReadT2()>>20, s); return; case 0x3E: Nunpack(a, ReadT2()>>24, s); return; case 0x3F: Nunpack(a, ReadT2()>>28, s); return; default: *a = Chipset.IORam[d]; } d++; a++; } while (--s); return; } VOID WriteIO(BYTE *a, DWORD b, DWORD s) { DWORD d=b; BYTE c; BYTE disp=0; if (d>=0x38) { Nunpack(Chipset.IORam+0x38, ReadT2(), 8); memcpy(Chipset.IORam+d,a,s); SetT2(Npack(Chipset.IORam+0x38,8)); return; } do { c = *a; switch (d) { // 00100 = NS:DISPIO // 00100 @ Display bit offset and DON [DON OFF2 OFF1 OFF0] // 00100 @ 3 nibs for display offset (scrolling), DON=Display ON case 0x00: if ((c^Chipset.IORam[d])&8) { Chipset.dispon = c>>3; disp|=7; } if ((c^Chipset.IORam[d])&7) { Chipset.boffset = c&7; disp|=3; } Chipset.IORam[d] = c; break; // 00101 = NS:CONTRLSB // 00101 @ Contrast Control [CON3 CON2 CON1 CON0] // 00101 @ Higher value = darker screen case 0x01: if (c!=Chipset.IORam[d]) { Chipset.IORam[d]=c; Chipset.contrast = (Chipset.contrast&0x10)|c; UpdateContrast(Chipset.contrast); disp|=7; } break; // 00102 = NS:DISPTEST // 00102 @ Display test [VDIG LID TRIM CON4] [LRT LRTD LRTC BIN] // 00102 @ Normally zeros case 0x02: if (c!=Chipset.IORam[d]) { Chipset.IORam[d]=c; Chipset.contrast = (Chipset.contrast&0x0f)|((c&1)<<4); UpdateContrast(Chipset.contrast); disp|=7; } break; case 0x03: Chipset.IORam[d]=c; break; // 00104 = HP:CRC // 00104 @ 16 bit hardware CRC (104-107) (X^16+X^12+X^5+1) // 00104 @ crc = ( crc >> 4 ) ^ ( ( ( crc ^ nib ) & 0x000F ) * 0x1081 ); case 0x04: Chipset.crc = (Chipset.crc&0xfff0)|(c*0x0001); break; case 0x05: Chipset.crc = (Chipset.crc&0xff0f)|(c*0x0010); break; case 0x06: Chipset.crc = (Chipset.crc&0xf0ff)|(c*0x0100); break; case 0x07: Chipset.crc = (Chipset.crc&0x0fff)|(c*0x1000); break; // 00108 = NS:POWERSTATUS // 00108 @ Low power registers (108-109) // 00108 @ [LB2 LB1 LB0 VLBI] (read only) // 00108 @ LowBat(2) LowBat(1) LowBat(S) VeryLowBat case 0x08: break; // read-only // 00109 = NS:POWERCTRL // 00109 @ [ELBI EVLBI GRST RST] (read/write) case 0x09: Chipset.IORam[d]=c; break; // 0010A = NS:MODE // 0010A @ Mode Register (read-only) case 0x0A: break; // read-only // 0010B = HP:ANNCTRL // 0010B @ Annunciator control [LA4 LA3 LA2 LA1] = [ alarm alpha -> <- ] case 0x0B: case 0x0C: if (c!=Chipset.IORam[d]) { Chipset.IORam[d] = c; disp|=8; } break; // 0010D = NS:BAU // 0010D @ Serial baud rate [UCK BD2 BD1 BD0] (bit 3 is read-only) // 0010D @ 3 bits = {1200 1920 2400 3840 4800 7680 9600 15360} case 0x0D: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); break; // bit 3 is read-only // 0010E = NS:CARDCTRL // 0010E @ [ECDT RCDT SMP SWINT] (read/write) // 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt case 0x0E: Chipset.IORam[d]=c; #if 1 if ( (RMap[4]!=(pbyRom+0x4000)) && (12 != c) ) { c |= 0x10; } #endif if (c&1) { Chipset.SoftInt = TRUE; bInterrupt = TRUE; } if (c&2) { Chipset.HST |= 8; // MP // Chipset.SoftInt = TRUE; // bInterrupt = TRUE; } break; // 0010F = NS:CARDSTATUS // 0010F @ [P2W P1W P2C P1C] (read-only) Port 2 writable .. Port 1 inserted case 0x0F: break; // read-only // 00110 = HP:IOC // 00110 @ Serial I/O Control [SON ETBE ERBF ERBZ] // 00110 @ Serial On, Interrupt On Recv.Buf.Empty, Full, Buzy case 0x10: Chipset.IORam[d]=c; break; // 00111 = HP:RCS // 00111 Serial Receive Control/Status [RX RER RBZ RBF] (bit 3 is read-only) case 0x11: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); break; // 00112 = HP:TCS // 00112 @ Serial Transmit Control/Status [BRK LPB TBZ TBF] case 0x12: Chipset.IORam[d]=c; break; // 00113 = HP:CRER // 00113 @ Serial Clear RER (writing anything clears RER bit) case 0x13: Chipset.IORam[0x11]&=0xB; Chipset.IORam[0x11]&=0xB; // 00114 = HP:RBR // 00114 @ Serial Receive Buffer Register (Reading clears RBF bit) // 00114 @ [RX RER RBZ RBF] case 0x14: break; // probably read-only case 0x15: break; // probably read-only // 00116 = HP:TBR // 00116 @ Serial Transmit Buffer Register (Writing sets TBF bit) case 0x16: Chipset.IORam[d]=c; Chipset.IORam[0x12]|=1; break; case 0x17: Chipset.IORam[d]=c; Chipset.IORam[0x12]|=1; break; // 00118 = NS:SRR // 00118 @ Service Request Register (read-only) // 00118 @ [ISRQ TSRQ USRQ VSRQ] [KDN NINT2 NINT LSRQ] case 0x18: break; // read-only case 0x19: break; // read-only // 0011A = HP:IRC // 0011A @ IR Control Register [IRI EIRU EIRI IRE] (bit 3 is read-only) // 0011A @ IR Input, Enable IR UART mode, Enable IR Interrupt, IR Event case 0x1A: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); break; // 0011B = NS:BASENIBOFF // 0011B @ Used as addressto get BASENIB from 11F to the 5th nibble case 0x1B: break; // 0011C = NS:LCR // 0011C @ Led Control Register [LED ELBE LBZ LBF] (Setting LED is draining) case 0x1C: Chipset.IORam[d]=c; break; // 0011D = NS:LBR // 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero) case 0x1D: Chipset.IORam[d]=c&1; break; // 0011E = NS:SCRATCHPAD // 0011E @ Scratch pad case 0x1E: Chipset.IORam[d]=c; break; // 0011F = NS:BASENIB // 0011F @ 7 or F for base memory case 0x1F: Chipset.IORam[d]=c; break; // 00120 = NS:DISPADDR // 00120 @ Display Start Address (write only) // 00120 @ bit 0 is ignored (display must start on byte boundary) case 0x20: if (s>=5) { b = Npack(a,5)&0xFFFFE; if (b != Chipset.start1) { Chipset.start1 = b; disp|=3; } b = d; } Chipset.IORam[d]=c; break; // case 0x21: Chipset.IORam[d]=c; break; // case 0x22: Chipset.IORam[d]=c; break; // case 0x23: Chipset.IORam[d]=c; break; // case 0x24: Chipset.IORam[d]=c; break; // 00125 = NS:LINEOFFS // 00125 @ Display Line offset (write only) (no of bytes skipped after each line) // 00125 @ MSG sign extended case 0x25: if (s>=3) { signed short lo = (signed short)Npack(a, 3); if (lo&0x800) lo-=0x1000; if (lo==Chipset.loffset) break; Chipset.loffset = lo; disp|=3; } break; // 00128 = NS:LINECOUNT // 00128 @ Display Line Counter and miscellaneous (28-29) // 00128 @ [LC3 LC2 LC1 LC0] [DA19 M32 LC5 LC4] // 00128 @ Line counter 6 bits -> max = 2^6-1 = 63 = disp height // 00128 @ Normally has 55 -> Menu starts at display row 56 case 0x28: Chipset.IORam[d]=c; break; case 0x29: Chipset.IORam[d]=c; d = Npack(Chipset.IORam+0x28,2)&0x3F; if (Chipset.lcounter != d) { Chipset.lcounter = d; disp|=7; } break; case 0x2A: break; case 0x2B: break; case 0x2C: break; case 0x2D: break; // 0012E = NS:TIMER1CTRL // 0012E @ TIMER1 Control [SRQ WKE INT XTRA] case 0x2E: Chipset.IORam[d]=c&0xE; break; // 0012F = NS:TIMER2CTRL // 0012F @ TIMER2 Control [SRQ WKE INT RUN] case 0x2F: // if ((Chipset.IORam[d]^c)&1) // // RUN changed Chipset.IORam[d]=c; if (c&1) StartTimers(); else StopTimers(); break; // 00130 = NS:MENUADDR // 00130 @ Display Secondary Start Address (write only) (30-34) // 00130 @ Menu Display Address, no line offsets case 0x30: if (s>=5) { b = Npack(a,5)&0xFFFFE; if (b != Chipset.start2) { Chipset.start2 = b; disp|=5; } b = d; } Chipset.IORam[d]=c; break; // case 0x31: Chipset.IORam[d]=c; break; // case 0x32: Chipset.IORam[d]=c; break; // case 0x33: Chipset.IORam[d]=c; break; // case 0x34: Chipset.IORam[d]=c; break; case 0x35: break; case 0x36: break; // 00137 = HP:TIMER1 // 00137 @ Decremented 16 times/s case 0x37: SetT1(Chipset.t1); break; // 00138 = HP:TIMER2 // 00138 @ hardware timer (38-3F), decremented 8192 times/s // nothing - fall through to default default: Chipset.IORam[d]=c; } a++; d++; } while (--s); if (disp&1) UpdateDisplayPointers(); if (disp&2) UpdateMainDisplay(); if (disp&4) UpdateMenuDisplay(); if (disp&8) UpdateAnnunciators(); return; }