Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
#include "std.h"
#include "emul.h"
#include "vars.h"
#include "memory.h"
#include "draw.h"
#include "atm.h"
#include "funcs.h" //NEDOREPO
//=============================================================================
static void atm_memswap()
{
// òàêîå øóñòâà, ÷òî ýòî ãàôíî ïåðåêèäûâàåò 2 ìåòðà ïàìÿòè
// à íå ïåðåïóòûâàåò ñðàíûå áèòû
// ïîòîì áóäåò êó÷à áàãîâ ñ äåáàãåðîì, áðÿêàìè èòä...
//-------------------------------------------------------------------------
if (!conf.atm.mem_swap)
return;
//-------------------------------------------------------------------------
// swap memory address bits A5-A7 and A8-A10
for (unsigned start_page = 0; start_page < conf.ramsize*1024; start_page += 2048)
{
unsigned char buffer[2048], *bank = memory + start_page;
//---------------------------------------------------------------------
for (unsigned addr = 0; addr < 2048; addr++)
buffer[addr] = bank[(addr & 0x1F) + ((addr >> 3) & 0xE0) + ((addr << 3) & 0x700)];
//---------------------------------------------------------------------
memcpy(bank, buffer, 2048);
}
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
static void AtmApplySideEffectsWhenChangeVideomode(unsigned char val)
{
int NewVideoMode = (val & 7);
int OldVideoMode = (comp.pFF77 & 7);
// Êîíñòàíòû ìîæíî çàäàòü æ¸ñòêî, ïîòîìó ÷òî ìåæäó ìîäåëÿìè ÀÒÌ2 îíè íå ìåíÿþòñÿ.
const int tScanlineWidth = 224;
const int tScreenWidth = 320/2;
const int tEachBorderWidth = (tScanlineWidth - tScreenWidth)/2;
const int iLinesAboveBorder = 56;
int iRayLine = cpu.t / tScanlineWidth;
int iRayOffset = cpu.t % tScanlineWidth;
/*
static int iLastLine = 0;
if ( iLastLine > iRayLine )
{
printf("\nNew Frame Begin\n");
__debugbreak();
}
iLastLine = iRayLine;
printf("%d->%d %d %d\n", OldVideoMode, NewVideoMode, iRayLine, iRayOffset);
*/
//-------------------------------------------------------------------------
if ((OldVideoMode == 3) || (NewVideoMode == 3))
{
// Ïåðåêëþ÷åíèå èç/â sinclair ðåæèì íå èìååò ïîëåçíûõ ïîáî÷íûõ ýôôåêòîâ
// (ïî ñëîâàì AlCo äàæå ñèíõðà ñáèâàåòñÿ)
for (unsigned y = 0; y < 200; y++)
{
AtmVideoCtrl.Scanlines[y+56].VideoMode = NewVideoMode;
AtmVideoCtrl.Scanlines[y+56].Offset = int(((y & ~7U) << 3) + 0x01C0);
}
return;
}
//-------------------------------------------------------------------------
if ((OldVideoMode != 6) && (NewVideoMode != 6))
{
// Íàñ èíòåðåñóþò òîëüêî ïåðåêëþ÷åíèÿ ìåæäó òåêñòîâûì ðåæèìîì è ðàñøèðåííûìè ãðàôè÷åñêèìè.
// Òåêñòîâîãî ðåæèìà íåò íè äî, íè ïîñëå ïåðåêëþ÷åíèÿ.
// Ñëåäîâàòåëüíî, íåò è ïîáî÷íûõ ýôôåêòîâ.
//---------------------------------------------------------------------
// Ðàñïðîñòðàíÿåì íîâûé âèäåîðåæèì íà íåîòðèñîâàííûå ñêàíëèíèè
if (iRayOffset >= tEachBorderWidth)
++iRayLine;
//---------------------------------------------------------------------
while (iRayLine < 256)
{
AtmVideoCtrl.Scanlines[iRayLine++].VideoMode = NewVideoMode;
}
// printf("%d->%d SKIPPED!\n", OldVideoMode, NewVideoMode);
return;
}
//-------------------------------------------------------------------------
//
// Òåðìèíîëîãèÿ è êîíñòàíòû:
// Ýêðàí ñîäåðæèò 312 ñêàíëèíèé, ïî 224òàêòà (noturbo) â êàæäîé.
//
// "ñòðîêà" - ìëàäøèå 3 áèòà íîìåðà îòðèñîâûâàåìîé âèäåîêîíòðîëëåðîì (ëó÷îì) ñêàíëèíèè
// "àäðåñ" - òåêóùèé àäðåñ â âèäåîïàìÿòè, ñ êîòîðîãî âûáèðàåò áàéòû âèäåîêîíòðîëëåð
// àäðåñ ìåíÿåòñÿ ñ ãðàíóëÿðíîñòüþ +8 èëè +64
// "ýêðàí" - ðàñòðîâàÿ êàðòèíêà. Ñî âñåõ ñòîðîí îêðóæåíà "áîðäþðîì".
// Ðàçìåðû áîðäþðà:
// ñâåðõó è ñíèçó îò ðàñòðà: 56 ñêàíëèíèé
// ñëåâà è ñïðàâà îò ðàñòðà: 32 òàêòà (64 ïèêñåëÿ).
//
// +64 ïðîèñõîäèò, êîãäà CROW 1->0, òî åñòü:
// ëèáî â òåêñòìîäå ïðè ïåðåõîäå ñî ñòðîêè 7 íà ñòðîêó 0,
// ëèáî ïðè ïåðåêëþ÷åíèè òåêñòìîä->ãðàôèêà ïðè àäðåñå A5=0,
// ëèáî ïðè ïåðåêëþ÷åíèè ãðàôèêà->òåêñòìîä ïðè àäðåñå A5=1 è ñòðîêå 0..3
//
// +8 ïðîèñõîäèò íà ðàñòðå â êîíöå 64-áëîêà ïèêñåëåé (êàæäûå 32òàêòà) íåçàâèñèìî îò ðåæèìà
// (ÂÀÆÍÎ: +8 íå çàâðàïëåíû âíóòðè A3..A5 à ïðîèçâîäÿò ÷åñòíîå ñëîæåíèå ñ àäðåñîì.)
//
// ñáðîñ A3..A5 (íàêîïëåííûõ +8) ïðîèñõîäèò, êîãäà RCOL 1->0, òî åñòü:
// ëèáî â òåêñòìîäå ïðè ïåðåõîäå ñ ðàñòðà íà áîðäþð,
// ëèáî íà áîðäþðå ïðè ïåðåêëþ÷åíèè ãðàôèêà->òåêñòìîä
//
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
if (iRayLine >= 256)
{
return;
}
//-------------------------------------------------------------------------
// Ïîëó÷èì îôôñåò òåêóùåé ñêàíëèíèè (ôàêòè÷åñêè âèäåîàäðåñ å¸ íà÷àëà)
int Offset = AtmVideoCtrl.Scanlines[iRayLine].Offset;
// Âû÷èñëèì ðåàëüíûé âèäåîàäðåñ, ñ ó÷¸òîì èíêðåìåíòîâ ïðè îòðèñîâêå ðàñòðà.
// Òàêæå îïðåäåëèì, êóäà ïðèìåíÿåì +64 èíêðåìåíòû ïðè ïåðåêëþ÷åíèè âèäåîðåæèìà:
// - Åñëè ëó÷ íà áîðäþðå ñâåðõó îò ðàñòðà èëè íà áîðäþðå ñëåâà îò ðàñòðà
// - èçìåíÿåì îôôñåò äëÿ òåêóùåé ñêàíëèíèè
// - Åñëè ëó÷ íà ðàñòðå èëè íà áîðäþðå ñïðàâà îò ðàñòðà
// - èçìåíÿåì îôôñåò äëÿ ñëåäóþùåé ñêàíëèíèè
//-------------------------------------------------------------------------
if ( iRayLine < iLinesAboveBorder || iRayOffset < tEachBorderWidth )
{
// Ëó÷ íà áîðäþðå. Ëèáî ñâåðõó îò ðàñòðà, ëèáî ñëåâà îò ðàñòðà.
// Âñå èçìåíåíèÿ ïðèìåíÿåì ê òåêóùåé ñêàíëèíèè.
//---------------------------------------------------------------------
// Îáðàáîòàåì ïåðåêëþ÷åíèå âèäåîðåæèìà.
if ( NewVideoMode == 6 )
{
//-----------------------------------------------------------------
// Ïåðåêëþ÷åíèå  òåêñòîâûé ðåæèì.
//-----------------------------------------------------------------
if ( (Offset & 32) && //< ïðîâåðêà óñëîâèÿ "ïðè àäðåñå A5=1"
(iRayLine & 7) < 4 //< ïðîâåðêà óñëîâèÿ "â ñòðîêå 0..3"
)
{
// printf("CASE-1: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
Offset += 64;
AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
}
//-----------------------------------------------------------------
AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
//-----------------------------------------------------------------
// Ïîñëå ïðîõîäà âñåõ òî÷åê ðàñòðà òåêóùåé ñêàíëèíèè â òåêñòîâîì ðåæèìå áóäóò ñáðîøåíû A3..A5
Offset &= (~0x38); // Ñáðîñ A3..A5
// printf("CASE-1a, reset A3..A5: 0x%.4x\n", Offset);
//-----------------------------------------------------------------
// Ðàññ÷¸ò âèäåîàäðåñîâ äëÿ íèæëåæàùèõ ñêàíëèíèé
while (++iRayLine < 256)
{
//-------------------------------------------------------------
if ( 0 == (iRayLine & 7))
{
Offset += 64;
}
//-------------------------------------------------------------
AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
}
} //if ( NewVideoMode == 6 )
//---------------------------------------------------------------------
else
{
//-----------------------------------------------------------------
// Ïåðåêëþ÷åíèå ÈÇ òåêñòîâîãî ðåæèìà.
//-----------------------------------------------------------------
if ( 0 == (Offset & 32) ) //< ïðîâåðêà óñëîâèÿ "ïðè àäðåñå A5=0"
{
// printf("CASE-2: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
Offset += 64;
AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
}
//-----------------------------------------------------------------
AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
//-----------------------------------------------------------------
// Ðàññ÷¸ò âèäåîàäðåñîâ äëÿ íèæëåæàùèõ ñêàíëèíèé
while (++iRayLine < 256)
{
AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
}
//-----------------------------------------------------------------
}
} // if ( iRayLine < iLinesAboveBorder || iRayOffset < tEachBorderWidth )
//-------------------------------------------------------------------------
else
{
// Ëó÷ ðèñóåò ðàñòð, ëèáî áîðäþð ñïðàâà îò ðàñòðà.
// Âû÷èñëÿåì òåêóùåå çíà÷åíèå âèäåîàäðåñà
//---------------------------------------------------------------------
// Ïðèáàâëÿåì ê âèäåîàäðåñó âñå +64 èíêðåìåíòû,
// ñäåëàííûå â õîäå îòðèñîâêè ðàñòðà äàííîé ñêàíëèíèè
if (iRayLine == AtmVideoCtrl.CurrentRayLine)
{
Offset += AtmVideoCtrl.IncCounter_InRaster;
}
//---------------------------------------------------------------------
else
{
// Ñ÷¸ò÷èê èíêðåìåíòîâ óñòàðåë (ò.ê. íàêðó÷åí íà ñêàíëèíèþ îòëè÷íóþ îò òåêóùåé)
// Èíèöèàëèçèðóåì åãî äëÿ òåêóùåé ñêàíëèíèè.
AtmVideoCtrl.CurrentRayLine = iRayLine;
AtmVideoCtrl.IncCounter_InRaster = 0;
AtmVideoCtrl.IncCounter_InBorder = 0;
}
//---------------------------------------------------------------------
// Ïðèáàâëÿåì ê âèäåîàäðåñó âñå +8 èíêðåìåíòû, ïðîèçîøåäøèå ïðè îòðèñîâêå ðàñòðà
bool bRayInRaster = iRayOffset < (tScreenWidth + tEachBorderWidth);
int iScanlineRemainder = 0; //< Ñêîëüêî +8 èíêðåìåíòîâ åù¸ áóäåò ñäåëàíî äî êîíöà ñêàíëèíèè
// (ò.å. óæå ïîñëå ïåðåêëþ÷åíèÿ âèäåîðåæèìà)
//---------------------------------------------------------------------
if ( bRayInRaster )
{
// Ëó÷ ðèñóåò ðàñòð.
// Ïðèáàâëÿåì ê òåêóùåìó âèäåîàäðåñó ñòîëüêî +8,
// ñêîëüêî áûëî ïîëíîñòüþ îòðèñîâàííûõ 64ïèêñåëüíûõ áëîêà.
int iIncValue = 8 * ((iRayOffset-tEachBorderWidth)/32);
iScanlineRemainder = 40 - iIncValue;
// printf("CASE-4: 0x%.4x Incremented (+%d) on line %d\n", Offset, iIncValue, iRayLine);
Offset += iIncValue;
}
//---------------------------------------------------------------------
else
{
// Îòðèñîâêà ðàñòðà ëó÷îì çàâåðøåíà.
// Ò.å. âñå 5-ÿòü 64-ïèêñåëüíûõ áëîêà áûëè ïðîéäåíû. Ïðèáàâëÿåì ê àäðåñó +40.
// printf("CASE-5: 0x%.4x Incremented (+40) on line %d\n", Offset, iRayLine);
Offset += 40;
// Åñëè ïðåäûäóùèì ðåæèìîì áûë òåêñòîâûé ðåæèì,
// Òî ïðè ïåðåõîäå ñ ðàñòðà íà áîðäþð äîëæíû áûòü ñáðîøåíû A3..A5
//-----------------------------------------------------------------
if (OldVideoMode == 6)
{
Offset &= (~0x38); // Ñáðîñ A3..A5
// printf("CASE-5a, reset A3..A5: 0x%.4x\n", Offset);
}
}
//---------------------------------------------------------------------
// Ïðèáàâëÿåì ê âèäåîàäðåñó âñå +64 èíêðåìåíòû,
// ñäåëàííûå â õîäå îòðèñîâêè áîðäþðà çà ðàñòðîì äàííîé ñêàíëèíèè
Offset += AtmVideoCtrl.IncCounter_InBorder;
// Òåêóùåå çíà÷åíèå âèäåîàäðåñà âû÷èñëåíî.
// Îáðàáàòûâàåì ïåðåêëþ÷åíèå âèäåîðåæèìà.
int OffsetInc = 0;
//---------------------------------------------------------------------
if ( NewVideoMode == 6 )
{
// Ïåðåêëþ÷åíèå  òåêñòîâûé ðåæèì.
//-----------------------------------------------------------------
if ( (Offset & 32) && //< ïðîâåðêà óñëîâèÿ "ïðè àäðåñå A5=1"
(iRayLine & 7) < 4 //< ïðîâåðêà óñëîâèÿ "â ñòðîêå 0..3"
)
{
OffsetInc = 64;
// printf("CASE-6: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
Offset += OffsetInc;
}
//-----------------------------------------------------------------
// Ðàññ÷¸ò âèäåîàäðåñîâ äëÿ íèæëåæàùèõ ñêàíëèíèé
Offset += iScanlineRemainder;
//-----------------------------------------------------------------
while (++iRayLine < 256)
{
//-------------------------------------------------------------
if ( 0 == (iRayLine & 7))
Offset += 64;
//-------------------------------------------------------------
AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
}
//-----------------------------------------------------------------
} // if ( NewVideoMode == 6 )
//---------------------------------------------------------------------
else
{
// Ïåðåêëþ÷åíèå ÈÇ òåêñòîâîãî ðåæèìà.
//-----------------------------------------------------------------
if ( 0 == (Offset & 32) ) //< ïðîâåðêà óñëîâèÿ "ïðè àäðåñå A5=0"
{
OffsetInc = 64;
// printf("CASE-7: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
Offset += OffsetInc;
}
//-----------------------------------------------------------------
// Ðàññ÷¸ò âèäåîàäðåñîâ äëÿ íèæëåæàùèõ ñêàíëèíèé
Offset += iScanlineRemainder;
//-----------------------------------------------------------------
while (++iRayLine < 256)
{
AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
Offset += 40;
}
//-----------------------------------------------------------------
}
//---------------------------------------------------------------------
// çàïîìèíàåì ñäåëàííûé èíêðåìåíò íà ñëó÷àé,
// åñëè èõ áóäåò íåñêîëüêî â õîäå îòðèñîâêè òåêóùåé ñêàíëèíèè.
if ( bRayInRaster )
{
AtmVideoCtrl.IncCounter_InRaster += OffsetInc;
}
//---------------------------------------------------------------------
else
{
AtmVideoCtrl.IncCounter_InBorder += OffsetInc;
}
//---------------------------------------------------------------------
}
}
//=============================================================================
//=============================================================================
void set_atm_FF77(unsigned port, unsigned char val)
{
//-------------------------------------------------------------------------
if ((comp.pFF77 ^ val) & 1)
atm_memswap(); // àòýýìî áàãà swap memory address bits A5-A7 and A8-A10
//-------------------------------------------------------------------------
if ((comp.pFF77 & 7) ^ (val & 7))
{
// Ïðîèñõîäèò ïåðåêëþ÷åíèå âèäåîðåæèìà
AtmApplySideEffectsWhenChangeVideomode(val);
}
//-------------------------------------------------------------------------
comp.pFF77 = val;
comp.aFF77 = port;
cpu.int_gate = (comp.pFF77 & 0x20) != false;
set_banks();
}
//=============================================================================
//=============================================================================
void set_atm_aFE(unsigned char addr)
{
unsigned char old_aFE = comp.aFE;
comp.aFE = addr;
//-------------------------------------------------------------------------
if ((addr ^ old_aFE) & 0x40) atm_memswap(); // àòýýìî áàãà swap memory address bits A5-A7 and A8-A10
if ((addr ^ old_aFE) & 0x80) set_banks();
//-------------------------------------------------------------------------
}
//=============================================================================
static u8 atm_pal[0x10] = { 0 };
//static u16 atm3_pal[0x10] = { 0 };
//void atm_writepal(unsigned char val)
//=============================================================================
void atm_writepal(unsigned port, unsigned char val)
{
assert(comp.border_attr < 0x10);
atm_pal[comp.border_attr] = val;
// Ïðåîáðàçîâàíèå ïàëèòðû â ôîðìàò ULA+
u8 PalIdx = ((comp.border_attr & 8) << 1) | (comp.border_attr & 7);
comp.comp_pal[PalIdx + 0*8] =
comp.comp_pal[PalIdx + 1*8] =
comp.comp_pal[PalIdx + 3*8] =
comp.comp_pal[PalIdx + 5*8] = u8(t.atm_pal_map[val]);
temp.comp_pal_changed = 1; //to call pixel_tables()
// ÑÞÄÀ ÍÀÄÎ ÂÛÊËÞ×ÀÒÅËÜ?
//added by Alone Coder 04.12.2021: //NEDOREPO
comp.atm3_pal[comp.border_attr] = (val & 0xFF) + (port & 0xFF00); //%grbG11RB(low), %grbG11RB(high), inverted
// transform with current settings
}
//=============================================================================
//=============================================================================
u8 atm_readpal()
{
return atm_pal[comp.border_attr];
}
//=============================================================================
//=============================================================================
// êîïèðàñòèÿ
//=============================================================================
//inline
unsigned char atm450_z(unsigned t)
{
// PAL hardware gives 3 zeros in secret short time intervals
// ÷å åùå çà PAL hardware ???
//-------------------------------------------------------------------------
// NORMAL SPEED mode
if (conf.frame < 80000)
{
if ((unsigned)(t-7200) < 40 || (unsigned)(t-7284) < 40 || (unsigned)(t-7326) < 40)
return 0;
}
//-------------------------------------------------------------------------
// TURBO mode ???????? o_O
else
{
if ((unsigned)(t-21514) < 40 || (unsigned)(t-21703) < 80 || (unsigned)(t-21808) < 40)
return 0;
}
//-------------------------------------------------------------------------
return 0x80;
}
//=============================================================================
//inline
unsigned char atm620_z(unsigned t) //[NS]
{
// äëÿ çàïóñêà MSX-DOS
//-------------------------------------------------------------------------
if ( ((unsigned)(t) >= 0) && // ïðåäïîëîæåíèå íà îñíîâå êîäà ïðîâåðêè
((unsigned)(t) < 1024) // âîçìîæíî òàì âîîáùå ìåàíäð
)
{
//printf("t %d = 0\n",t);
return 0;
}
//-------------------------------------------------------------------------
//printf("t %d = 1\n",t);
return 0x20;
}
//=============================================================================