emu48-mirror/sources/Emu48/MOPS.C
2024-03-19 22:24:30 +01:00

1377 lines
38 KiB
C

/*
* mops.c
*
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
*
*/
#include "pch.h"
#include "Emu48.h"
// #define DEBUG_SERIAL // 17.05.98 cg, new, switch for SERIAL debug purpose
// #define DEBUG_IO // 21.01.99 cg, new, switch for IO debug purpose
// 30.06.98 cg, new, on mapping boundary adjusted base addresses
#define P0MAPBASE ((BYTE)(Chipset.P0Base & ~Chipset.P0Size))
#define P1MAPBASE ((BYTE)(Chipset.P1Base & ~Chipset.P1Size))
#define P2MAPBASE ((BYTE)(Chipset.P2Base & ~Chipset.P2Size))
#define BSMAPBASE ((BYTE)(Chipset.BSBase & ~Chipset.BSSize))
BOOL ioc_acc = FALSE; // 17.05.98 cg, new, flag ioc changed
BOOL ir_ctrl_acc = FALSE; // 17.05.98 cg, new, flag ir_ctl changed
static BYTE byVblRef = 0; // 14.01.99 cg, new, VBL stop reference
// 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]);
}
// LCD line counter calculation
static BYTE F4096Hz(VOID) // 14.01.99 cg, new, get a 6 bit 4096Hz down counter value
{
LARGE_INTEGER lLC;
QueryPerformanceCounter(&lLC); // get counter value
// calculate 4096 Hz frequency down counter value
return -(BYTE)((lLC.LowPart * 4096) / lFreq.LowPart) & 0x3F;
}
// port mapping
LPBYTE RMap[256] = {NULL,};
LPBYTE WMap[256] = {NULL,};
static __inline UINT MIN(UINT a, UINT b)
{
return (a<b)?a:b;
}
static __inline UINT MAX(UINT a, UINT b)
{
return (a>b)?a:b;
}
static VOID MapP0(BYTE a, BYTE b)
{
UINT i;
DWORD p, m;
a = (BYTE)MAX(a,P0MAPBASE); // 30.06.98 cg, bugfix, adjust base to mapping boundary
b = (BYTE)MIN(b,Chipset.P0End);
m = (Chipset.Port0Size*2048)-1;
p = (a<<12)&m; // 29.06.98 cg, bugfix, offset to begin of P0 in nibbles
for (i=a; i<=b; i++)
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.P0Base) & ~Chipset.P0Size) == 0)
{
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; // 15.12.98 cg, removed
a = (BYTE)MAX(a,BSMAPBASE); // 30.06.98 cg, bugfix, adjust base to mapping boundary
b = (BYTE)MIN(b,Chipset.BSEnd);
// m = (dwRomSize-1)&0xFF000; // 15.12.98 cg, removed
// p = (a*0x1000)&m; // 15.12.98 cg, removed
for (i=a;i<=b;i++)
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.BSBase) & ~Chipset.BSSize) == 0)
{
RMap[i] = NULL; // 15.12.98 cg, bugfix, no read cycle, open data bus
WMap[i] = NULL;
}
// p = (p+0x1000)&m; // 15.12.98 cg, removed
}
return;
}
static VOID MapP1(BYTE a, BYTE b)
{
UINT i;
DWORD p, m;
if (Chipset.Port1 == NULL) return; // memory for port1 allocated
// 30.06.98 cg, bugfix, adjust base to mapping boundary
a = (BYTE)MAX(a,P1MAPBASE); // lowest address for use is P1Base
b = (BYTE)MIN(b,Chipset.P1End); // highest address for use is P1End
m = (Chipset.Port1Size*2048)-1; // real size of module, address mask for mirroring
p = (a<<12)&m; // 29.06.98 cg, bugfix, offset to begin of P1 in nibbles
if (Chipset.Port1_Writeable) // port1 write enabled
{
for (i=a; i<=b; i++) // scan each 2KB page
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0)
{
RMap[i]=Chipset.Port1 + p; // save page address for read
WMap[i]=Chipset.Port1 + p; // save page address for write
}
p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size
}
}
else // port1 read only
{
for (i=a; i<=b; i++) // scan each 2KB page
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0)
{
RMap[i]=Chipset.Port1 + p; // save page address for read
WMap[i]=NULL; // no writing
}
p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size
}
}
return;
}
static VOID MapP2(BYTE a, BYTE b)
{
UINT i;
DWORD p, m;
LPBYTE pbyTemp;
if (pbyPort2 == NULL) return; // no port2 defined
// 15.12.98 cg, changed, Chipset.Port2_Bank now is the saved port2 FF content
pbyTemp = pbyPort2 + ((((Chipset.Port2_Bank-1)&dwPort2Mask)>>1) << 18);
a = (BYTE)MAX(a,P2MAPBASE); // 30.06.98 cg, bugfix, adjust base to mapping boundary
b = (BYTE)MIN(b,Chipset.P2End);
m = (dwPort2Size*2048)-1; // 26.06.98 cg, bugfix, real size of module, address mask for mirroring
p = (a<<12)&m; // 29.06.98 cg, bugfix, offset to begin of P2 in nibbles
// 15.12.98 cg, bugfix, only fill mapping table when CE2.2 is set
for (i=a; i<=b; i++) // fill mapping area with not configured
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0)
{
RMap[i] = NULL;
WMap[i] = NULL;
}
}
// SX: CE2.2 = CE2
// GX: CE2.2 = BEN & /DA19 & /NCE3
if (cCurrentRomType == 'S' || ((Chipset.IORam[0x29]&0x8) == 0 && (Chipset.Port2_Bank&0x40)))
{
if (bPort2Writeable)
{
for (i=a; i<=b; i++)
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0)
{
RMap[i]=pbyTemp + p;
WMap[i]=pbyTemp + p;
}
p = (p+0x1000)&m;
}
}
else
{
for (i=a; i<=b; i++)
{
// 21.01.99 cg, bugfix, mapping area may have holes
if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0)
{
RMap[i]=pbyTemp + p;
}
p = (p+0x1000)&m;
}
}
}
// 15.12.98 cg, end of bugfix
return;
}
static VOID MapROM(BYTE a, BYTE b)
{
UINT i;
DWORD p, m;
m = (dwRomSize-1)&0xFF000; // ROM address mask for mirroring
// 15.12.98 cg, bugfix, when G(X) ROM and DA19=0 (ROM disabled)
if (cCurrentRomType != 'S' && (Chipset.IORam[0x29]&0x8) == 0)
m >>= 1; // mirror ROM at #80000 (AR18=0)
// 15.12.98 cg, end of bugfix
p = (a*0x1000)&m; // 27.06.98 cg, bugfix, data offset in nibbles
for (i=a;i<=b;i++) // scan each 2KB page
{
RMap[i]=pbyRom + p; // save page address for read
WMap[i]=NULL; // no writing
p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size
}
return;
}
VOID Map(BYTE a, BYTE b) // maps 2KB pages with priority
{
// 25.06.98 cg, size optimized implementation
// priority order is HDW, RAM, CE2, CE1, NCE3, ROM
MapROM(a,b); // ROM, lowest priority, always mapped
if (cCurrentRomType=='S')
{
if (Chipset.BSCfig) MapBS(a,b); // NCE3, not used in S(X)
if (Chipset.P1Cfig) MapP1(a,b); // 25.06.98 cg, bugfix, CE1, port1 (lower priority than CE2)
if (Chipset.P2Cfig) MapP2(a,b); // 25.06.98 cg, bugfix, CE2, port2 (higher priority than CE1)
}
else
{
if (Chipset.P2Cfig) MapP2(a,b); // NCE3, port2
if (Chipset.BSCfig) MapBS(a,b); // 25.06.98 cg, bugfix, CE1, bank select (lower priority than CE2)
if (Chipset.P1Cfig) MapP1(a,b); // 25.06.98 cg, bugfix, CE2, port1 (higher priority than CE1)
}
if (Chipset.P0Cfig) MapP0(a,b); // RAM, highest priority (execpt HDW)
return;
}
////////////////////////////////////////////////////////////////////////////////
//
// Bus Commands
//
////////////////////////////////////////////////////////////////////////////////
VOID Config() // configure modules in fixed order
{
DWORD d = Npack(Chipset.C,5); // decode size or address
BYTE b = (BYTE)(d>>12); // number of 2KB pages or page address
BYTE s = (BYTE)(b^0xFF); // size in pages-1, offset to last page
// 25.06.98 cg, size optimized implementation
// config order is HDW, RAM, CE1, CE2, NCE3
if (!Chipset.IOCfig) // address of HDW, first module, ROM always configured
{
Chipset.IOCfig = TRUE;
Chipset.IOBase = d&0xFFFC0; // save HDW base on a 64 nib boundary
Map(b,b);
return;
}
if (!Chipset.P0Cfg2) // RAM size, port0
{
Chipset.P0Cfg2 = TRUE;
Chipset.P0Size = s; // offset to last used page
return;
}
if (!Chipset.P0Cfig) // RAM address, port0
{
Chipset.P0Cfig = TRUE;
Chipset.P0Base = b; // save first page address
b &= ~Chipset.P0Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.P0End = b+Chipset.P0Size; // save last page address
Map(b,Chipset.P0End); // 30.06.98 cg, bugfix, refresh mapping
return;
}
if (cCurrentRomType=='S')
{
if (!Chipset.P1Cfg2) // CE1 size, port1
{
Chipset.P1Cfg2 = TRUE;
Chipset.P1Size = s;
return;
}
if (!Chipset.P1Cfig) // CE1 address, port1
{
Chipset.P1Cfig = TRUE;
Chipset.P1Base = b;
b &= ~Chipset.P1Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.P1End = b+Chipset.P1Size;
Map(b,Chipset.P1End); // 30.06.98 cg, bugfix, refresh mapping
return;
}
if (!Chipset.P2Cfg2) // CE2 size, port2
{
Chipset.P2Cfg2 = TRUE;
Chipset.P2Size = s;
return;
}
if (!Chipset.P2Cfig) // CE2 address, port2
{
Chipset.P2Cfig = TRUE;
Chipset.P2Base = b;
b &= ~Chipset.P2Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.P2End = b+Chipset.P2Size;
Map(b,Chipset.P2End); // 30.06.98 cg, bugfix, refresh mapping
return;
}
if (!Chipset.BSCfg2) // NCE3 size, not used in S(X)
{
Chipset.BSCfg2 = TRUE;
Chipset.BSSize = s;
return;
}
if (!Chipset.BSCfig) // NCE3 address, not used in S(X)
{
Chipset.BSCfig = TRUE;
Chipset.BSBase = b;
b &= ~Chipset.BSSize; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.BSEnd = b+Chipset.BSSize;
Map(b,Chipset.BSEnd); // 30.06.98 cg, bugfix, refresh mapping
return;
}
}
else
{
if (!Chipset.BSCfg2) // CE1 size, bank select
{
Chipset.BSCfg2 = TRUE;
Chipset.BSSize = s;
return;
}
if (!Chipset.BSCfig) // CE1 address, bank select
{
Chipset.BSCfig = TRUE;
Chipset.BSBase = b;
b &= ~Chipset.BSSize; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.BSEnd = b+Chipset.BSSize;
Map(b,Chipset.BSEnd); // 30.06.98 cg, bugfix, refresh mapping
return;
}
if (!Chipset.P1Cfg2) // CE2 size, port1
{
Chipset.P1Cfg2 = TRUE;
Chipset.P1Size = s;
return;
}
if (!Chipset.P1Cfig) // CE2 address, port1
{
Chipset.P1Cfig = TRUE;
Chipset.P1Base = b;
b &= ~Chipset.P1Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.P1End = b+Chipset.P1Size;
Map(b,Chipset.P1End); // 30.06.98 cg, bugfix, refresh mapping
return;
}
if (!Chipset.P2Cfg2) // NCE3 size, port2
{
Chipset.P2Cfg2 = TRUE;
Chipset.P2Size = s;
return;
}
if (!Chipset.P2Cfig) // NCE3 address, port2
{
Chipset.P2Cfig = TRUE;
Chipset.P2Base = b;
b &= ~Chipset.P2Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary
Chipset.P2End = b+Chipset.P2Size;
Map(b,Chipset.P2End); // 30.06.98 cg, bugfix, refresh mapping
return;
}
}
return;
}
VOID Uncnfg()
{
DWORD d=Npack(Chipset.C,5); // decode address
BYTE b=(BYTE)(d>>12); // page address
// 25.06.98 cg, size optimized implementation
// unconfig order is HDW, RAM, CE2, CE1, NCE3
// 03.12.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
// 03.12.98 cg, bugfix, Chipset.IOBase must be saved for C=ID command
{Chipset.IOCfig=FALSE;Map(b,b);return;}
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.P0Cfig)&&((b&~Chipset.P0Size)==P0MAPBASE))
{Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Map(P0MAPBASE,Chipset.P0End);return;}
if (cCurrentRomType=='S')
{
// 25.06.98 cg, bugfix, CE2, port2 (higher priority than CE1)
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.P2Cfig)&&((b&~Chipset.P2Size)==P2MAPBASE))
{Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(P2MAPBASE,Chipset.P2End);return;}
// 25.06.98 cg, bugfix, CE1, port1 (lower priority than CE2)
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.P1Cfig)&&((b&~Chipset.P1Size)==P1MAPBASE))
{Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(P1MAPBASE,Chipset.P1End);return;}
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.BSCfig)&&((b&~Chipset.BSSize)==BSMAPBASE))
{Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(BSMAPBASE,Chipset.BSEnd);return;}
}
else
{
// 25.06.98 cg, bugfix, CE2, port1 (higher priority than CE1)
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.P1Cfig)&&((b&~Chipset.P1Size)==P1MAPBASE))
{Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(P1MAPBASE,Chipset.P1End);return;}
// 25.06.98 cg, bugfix, CE1, bank select (lower priority than CE2)
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.BSCfig)&&((b&~Chipset.BSSize)==BSMAPBASE))
{Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(BSMAPBASE,Chipset.BSEnd);return;}
// 30.08.98 cg, bugfix, adjust base to mapping boundary
if ((Chipset.P2Cfig)&&((b&~Chipset.P2Size)==P2MAPBASE))
{Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(P2MAPBASE,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); // refresh mapping
return;
}
VOID C_Eq_Id()
{
// 25.06.98 cg, size optimized implementation
// config order is HDW, RAM, CE1, CE2, NCE3
// 03.12.98 cg, bugfix, don't shift Chipset.IOBase for ID
if (!Chipset.IOCfig) {Nunpack(Chipset.C,(Chipset.IOBase) ^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 (cCurrentRomType=='S')
{
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;}
}
else
{
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
{
// 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping
if ((Chipset.IOCfig)&&((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);
// 15.12.98 cg, bugfix, bank switching
if ((Chipset.BSCfig)&&((u&~Chipset.BSSize)==BSMAPBASE))
{
Chipset.Port2_Bank = v+c; // save FF value
Map(Chipset.P2Base,Chipset.P2End);
}
// 15.12.98 cg, end of bugfix
if ((p=RMap[u]) != NULL)
{
memcpy(a, p+v, c);
for (u=0; u<c; u++)
CRC(a[u]);
}
}
if (s-=c) {a+=c; d+=c;}
} while (s);
return;
}
VOID Nwrite(BYTE *a, DWORD d, UINT s)
{
DWORD u, v;
UINT c;
BYTE *p;
// 09.01.99 cg, bugfix, better check of boundaries
if ((d<Chipset.end1)&&(d+s>Chipset.start12))
{
p = a; // copy source ptr
u = d; // copy destination ptr
c = MIN(s,Chipset.end1-d); // number of nibbles to copy
if (d < Chipset.start12) // first address is out of display area
{
u = Chipset.start12; // set destination ptr to start of display area
c -= Chipset.start12 - d; // - number of bytes that aren't in display area
p += Chipset.start12 - d; // adjust source ptr
}
WriteToMainDisplay(p,u,c);
}
if ((d<Chipset.end2)&&(d+s>Chipset.start2))
{
p = a; // copy source ptr
u = d; // copy destination ptr
c = MIN(s,Chipset.end2-d); // number of nibbles to copy
if (d < Chipset.start2) // first address is out of display area
{
u = Chipset.start2; // set destination ptr to start of display area
c -= Chipset.start2 - d; // - number of bytes that are not in display area
p += Chipset.start2 - d; // adjust source ptr
}
WriteToMenuDisplay(p,u,c);
}
// 09.01.99 cg, end of bugfix
do
{
// 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping
if ((Chipset.IOCfig)&&((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;
}
#if 0
// 15.12.98, removed, replaced by function Nread()
VOID Nread2(BYTE *a, DWORD d)
{
DWORD u, v;
BYTE *p;
// 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping
if ((Chipset.IOCfig)&&((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;
}
#endif
#if 0
// 15.12.98, removed, replaced by function Nread()
VOID Nwrite2(BYTE *a, DWORD d)
{
DWORD u, v;
BYTE *p;
// 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping
if ((Chipset.IOCfig)&&((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.end1)&&(d>=Chipset.start12))
WriteToMainDisplay(a,d,2);
if ((d<Chipset.end2)&&(d>=Chipset.start2))
WriteToMenuDisplay(a,d,2);
if ((p=WMap[u]) != NULL)
{
*((WORD*)(p+v)) = *((WORD*)a);
}
return;
}
#endif
#if 0
// 15.12.98, removed, replaced by function Nread()
VOID Nread5(BYTE *a, DWORD d)
{
DWORD u, v;
BYTE *p;
// 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping
if ((Chipset.IOCfig)&&((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;
}
#endif
#if 0
// 15.12.98, removed, replaced by function Nread()
VOID Nwrite5(BYTE *a, DWORD d)
{
DWORD u, v;
BYTE *p;
// 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
{
Nwrite(a,d,5);
return;
}
v = d&0xFFF;
if (v>0xFFA) {Nwrite(a,d,5);return;}
if ((d<Chipset.end1)&&(d>=Chipset.start12)) WriteToMainDisplay(a,d,5);
if ((d<Chipset.end2)&&(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];
}
}
#endif
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 IOBit(DWORD d, BYTE b, BOOL s) // 24.02.99 cg, new, set/clear bit in I/O section
{
EnterCriticalSection(&csIOLock);
{
if (s)
Chipset.IORam[d] |= b; // set bit
else
Chipset.IORam[d] &= ~b; // clear bit
}
LeaveCriticalSection(&csIOLock);
}
VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name
{
// DWORD d = b; // 24.08.98 cg, removed
BYTE c = 0xFF; // 26.08.98 cg, new, LINECOUNT not initialized
BOOL rbr_acc = FALSE; // 17.05.98 cg, new, flag to receive data
#if defined DEBUG_IO // 21.01.99 cg, new
{
char buffer[256];
wsprintf(buffer,"%.5lx: IO read : %02x,%u\n",Chipset.pc,d,s);
OutputDebugString(buffer);
}
#endif
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[d]; break;
case 0x0A: *a = 0; break;
// case 0x0B: *a = Chipset.IORam[d]; break;
// case 0x0C: *a = Chipset.IORam[d]; break;
case 0x0D: // BAUD
*a = Chipset.IORam[d];
#if defined DEBUG_SERIAL // 17.05.98 cg, return BAUD value
{
char buffer[256];
wsprintf(buffer,"%.5lx: BAUD Read: %x\n",Chipset.pc,*a);
OutputDebugString(buffer);
}
#endif
break;
// case 0x0E: *a = Chipset.IORam[d]; break;
case 0x0F: *a = Chipset.cards_status; break;
case 0x10: // IO CONTROL
*a = Chipset.IORam[d]; // 17.05.98 cg, return IO CONTROL value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: IOC Read: %x\n",Chipset.pc,*a);
OutputDebugString(buffer);
}
#endif
break;
case 0x11: // RCS
*a = Chipset.IORam[d]; // 17.05.98 cg, return RCS value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: RCS Read: %x\n",Chipset.pc,*a);
OutputDebugString(buffer);
}
#endif
break;
case 0x12: // TCS
*a = Chipset.IORam[d]; // 17.05.98 cg, new, return TCS value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: TCS Read: %x\n",Chipset.pc,*a);
OutputDebugString(buffer);
}
#endif
break;
case 0x13: // CRER
*a = 0;
break;
case 0x14: // RBR LSB
case 0x15: // RBR MSB
Chipset.IORam[0x11]&=0xE;
*a = Chipset.IORam[d]; // 17.05.95, new, return RBR value
rbr_acc = TRUE; // 17.05.95, new, search for new RBR value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: RBR %s Read: %x\n",Chipset.pc,(d==0x14) ? "LSB" : "MSB",*a);
OutputDebugString(buffer);
}
#endif
break;
case 0x16: // TBR LSB
case 0x17: // TBR MSB
*a = 0;
break;
case 0x19: // SREQ? MSB
UpdateKdnBit(); // 25.02.99 cg, bugfix, update KDN bit
// no break!
case 0x18: // SREQ? LSB
*a = Chipset.IORam[d]; // 17.05.95, new, return SREQ value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: SEQ %s Read: %x\n",Chipset.pc,(d==0x18) ? "LSB" : "MSB",*a);
OutputDebugString(buffer);
}
#endif
break;
case 0x1A: // IR CONTROL
*a = Chipset.IORam[d]; // 17.05.98 cg, new, return IR CONTROL value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: IRC Read: %x\n",Chipset.pc,*a);
OutputDebugString(buffer);
}
#endif
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;
// 14.01.99 cg, bugfixed LINECOUNT implementation
case 0x28: // LINECOUNT LSB
case 0x29: // LINECOUNT MSB + DA19 M32
if (Chipset.IORam[0x00]&8) // display on
{
if (c == 0xFF) // no actual line information
{
// get LCD update line
c = (0x40 + F4096Hz() - byVblRef) & 0x3F;
// save line information in IO registers
Chipset.IORam[0x28] = c & 0xF;
Chipset.IORam[0x29] = (Chipset.IORam[0x29] & 0xC) | (c >> 4);
}
}
*a = Chipset.IORam[d];
if (d==0x29) // address 0x29 is mirrored to 0x2A-0x2D
{
Chipset.IORam[0x2A] = *a;
Chipset.IORam[0x2B] = *a;
Chipset.IORam[0x2C] = *a;
Chipset.IORam[0x2D] = *a;
}
break;
// case 0x2A: *a = 0; break;
// case 0x2B: *a = 0; break;
// case 0x2C: *a = 0; break;
// case 0x2D: *a = 0; break;
// 14.01.99 cg, end of bugfixed implementation
// 21.12.98 cg, bugfix, update timer control register before
case 0x2E:
ReadT1(); // dummy read for update timer1 control register
*a = Chipset.IORam[d];
break;
case 0x2F:
ReadT2(); // dummy read for update timer2 control register
*a = Chipset.IORam[d];
break;
// 21.12.98 cg, end of bugfix
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);
if (rbr_acc) CommReceive(); // 17.05.98 cg, new, look for new character
return;
}
VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name
{
// DWORD d=b; // 07.09.98 cg, removed
DWORD b; // 07.09.98 cg, new
BYTE c;
BYTE disp=0;
BOOL tbr_acc = FALSE; // 17.05.98 cg, new, flag to transmit data
BOOL bDISPADDR = FALSE; // 07.09.98 cg, new, flag addr 0x120-0x124 changed
BOOL bLINEOFFS = FALSE; // 07.09.98 cg, new, flag addr 0x125-0x127 changed
BOOL bLINECOUNT = FALSE; // 07.09.98 cg, new, flag addr 0x128-0x129 changed
BOOL bMENUADDR = FALSE; // 07.09.98 cg, new, flag addr 0x130-0x134 changed
#if defined DEBUG_IO // 21.01.99 cg, new
{
char buffer[256];
DWORD j;
int i;
i = wsprintf(buffer,"%.5lx: IO write: %02x,%u = ",Chipset.pc,d,s);
for (j = 0;j < s;++j,++i)
{
buffer[i] = a[j];
if (buffer[i] > 9) buffer[i] += 0x27;
buffer[i] += '0';
}
buffer[i++] = '\n';
buffer[i] = 0;
OutputDebugString(buffer);
}
#endif
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) // DON bit changed
{
Chipset.dispon = c>>3;
disp|=7;
// 14.01.99 cg, bugfix, adjust VBL counter start/stop values
if (Chipset.dispon) // display is on
{
// get positive VBL difference between now and stop time
byVblRef = ( 0x40
+ F4096Hz()
- (((Chipset.IORam[0x29] << 4) | Chipset.IORam[0x28]) & 0x3F)
) & 0x3F;
}
else // display is off
{
BYTE a[2];
ReadIO(a,0x28,2); // update VBL at display off time
}
// 14.01.99 cg, end of VBL adjust
}
if ((c^Chipset.IORam[d])&7) // OFF bits changed
{
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:BAUD
// 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); // bit 3 is read-only
CommSetBaud(); // 17.05.98 cg, new, set baudrate
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: BAUD write: %x\n",Chipset.pc,Chipset.IORam[d]);
OutputDebugString(buffer);
}
#endif
break;
// 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;
ioc_acc = TRUE; // 17.05.98 cg, new, new IOC
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: IOC write: %x\n",Chipset.pc,Chipset.IORam[d]);
OutputDebugString(buffer);
}
#endif
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);
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: RCS write: %x\n",Chipset.pc,Chipset.IORam[d]);
OutputDebugString(buffer);
}
#endif
break;
// 00112 = HP:TCS
// 00112 @ Serial Transmit Control/Status [BRK LPB TBZ TBF]
case 0x12:
Chipset.IORam[d]=c;
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: TCS write: %x\n",Chipset.pc,Chipset.IORam[d]);
OutputDebugString(buffer);
}
#endif
break;
// 00113 = HP:CRER
// 00113 @ Serial Clear RER (writing anything clears RER bit)
case 0x13:
Chipset.IORam[0x11]&=0xB;
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: CRER write: %x\n",Chipset.pc,Chipset.IORam[d]);
OutputDebugString(buffer);
}
#endif
break;
// 00114 = HP:RBR
// 00114 @ Serial Receive Buffer Register (Reading clears RBF bit)
// 00114 @ [RX RER RBZ RBF]
case 0x14: break; // read-only
case 0x15: break; // read-only
// 00116 = HP:TBR
// 00116 @ Serial Transmit Buffer Register (Writing sets TBF bit)
case 0x16:
case 0x17:
Chipset.IORam[d]=c;
Chipset.IORam[0x12]|=1;
tbr_acc = TRUE; // 17.05.98 cg, new, new TBR value
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: TBR %s write: %x\n",Chipset.pc,(d==0x16) ? "LSB" : "MSB",*a);
OutputDebugString(buffer);
}
#endif
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);
ir_ctrl_acc = TRUE; // 17.05.98 cg, new, new IR_CTRL
#if defined DEBUG_SERIAL
{
char buffer[256];
wsprintf(buffer,"%.5lx: IRC write: %x\n",Chipset.pc,Chipset.IORam[d]);
OutputDebugString(buffer);
}
#endif
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 8 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)
// 07.09.98 cg, bugfix, new implementation
case 0x20:
case 0x21:
case 0x22:
case 0x23:
case 0x24:
Chipset.IORam[d]=c;
bDISPADDR = TRUE; // addr 0x120-0x124 changed
break;
// 07.09.98 cg, end of new implementation
// 00125 = NS:LINEOFFS
// 00125 @ Display Line offset (write only) (no of bytes skipped after each line)
// 00125 @ MSG sign extended
// 07.09.98 cg, bugfix, new implementation
case 0x25:
case 0x26:
case 0x27:
Chipset.IORam[d]=c;
bLINEOFFS = TRUE; // addr 0x125-0x127 changed
break;
// 07.09.98 cg, end of new implementation
// 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
// 07.09.98 cg, bugfix, new implementation
case 0x28:
case 0x29:
// 15.12.98 cg, bugfix, when G(X) and writing to register 0x29
if (cCurrentRomType != 'S' && d == 0x29)
{
if ((c^Chipset.IORam[d])&8) // DA19 changed
{
Chipset.IORam[d]=c; // save new DA19
Map(0x00,0xFF); // new ROM mapping
}
}
// 15.12.98 cg, end of bugfix
Chipset.IORam[d]=c;
bLINECOUNT = TRUE; // addr 0x128-0x129 changed
break;
// 07.09.98 cg, end of new implementation
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; // 05.01.99 cg, bugfix, don't clear XTRA bit
ReadT1(); // 05.01.99 cg, bugfix, dummy read for checking control bits
break;
// 0012F = NS:TIMER2CTRL
// 0012F @ TIMER2 Control [SRQ WKE INT RUN]
case 0x2F:
Chipset.IORam[d]=c;
ReadT2(); // 05.01.99 cg, bugfix, dummy read for checking control bits
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
// 07.09.98 cg, bugfix, new implementation
case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
Chipset.IORam[d]=c;
bMENUADDR = TRUE; // addr 0x130-0x134 changed
break;
// 07.09.98 cg, end of new implementation
case 0x35: break;
case 0x36: break;
// 00137 = HP:TIMER1
// 00137 @ Decremented 16 times/s
case 0x37:
SetT1(c); // 11.06.98 cg, bugfix, set new value
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 (bDISPADDR) // 07.09.98 cg, new, addr 0x120-0x124 changed
{
b = Npack(Chipset.IORam+0x20,5)&0xFFFFE;
if (b != Chipset.start1)
{
Chipset.start1 = b;
disp|=3;
}
}
if (bLINEOFFS) // 07.09.98 cg, new, addr 0x125-0x127 changed
{
signed short lo = (signed short)Npack(Chipset.IORam+0x25,3);
if (lo&0x800) lo-=0x1000;
if (lo != Chipset.loffset)
{
Chipset.loffset = lo;
disp|=3;
}
}
if (bLINECOUNT) // 07.09.98 cg, new, addr 0x128-0x129 changed
{
b = Npack(Chipset.IORam+0x28,2)&0x3F;
if (Chipset.lcounter != b)
{
Chipset.lcounter = b;
disp|=7;
}
}
if (bMENUADDR) // 07.09.98 cg, new, addr 0x130-0x134 changed
{
b = Npack(Chipset.IORam+0x30,5)&0xFFFFE;
if (b != Chipset.start2)
{
Chipset.start2 = b;
disp|=5;
}
}
if (tbr_acc) CommTransmit(); // 17.05.98 cg, new, transmit char
if (disp&1) UpdateDisplayPointers();
if (disp&2) UpdateMainDisplay();
if (disp&4) UpdateMenuDisplay();
if (disp&8) UpdateAnnunciators();
return;
}