Subversion Repositories pentevo

Rev

Rev 796 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "emul.h"
4
#include "vars.h"
5
#include "memory.h"
6
#include "draw.h"
796 DimkaM 7
#include "atm.h"
716 lvd 8
 
796 DimkaM 9
static void atm_memswap()
716 lvd 10
{
11
   if (!conf.atm.mem_swap) return;
12
   // swap memory address bits A5-A7 and A8-A10
13
   for (unsigned start_page = 0; start_page < conf.ramsize*1024; start_page += 2048) {
14
      unsigned char buffer[2048], *bank = memory + start_page;
15
      for (unsigned addr = 0; addr < 2048; addr++)
16
         buffer[addr] = bank[(addr & 0x1F) + ((addr >> 3) & 0xE0) + ((addr << 3) & 0x700)];
17
      memcpy(bank, buffer, 2048);
18
   }
19
}
20
 
796 DimkaM 21
static void AtmApplySideEffectsWhenChangeVideomode(unsigned char val)
716 lvd 22
{
23
    int NewVideoMode = (val & 7);
24
    int OldVideoMode = (comp.pFF77 & 7);
25
 
26
    // ��������� ����� ������ �����, ������ ��� ����� �������� ���2 ��� �� ��������.
27
    const int tScanlineWidth = 224;
28
    const int tScreenWidth = 320/2;
29
    const int tEachBorderWidth = (tScanlineWidth - tScreenWidth)/2;
30
    const int iLinesAboveBorder = 56;
31
 
32
    int iRayLine = cpu.t / tScanlineWidth;
33
    int iRayOffset = cpu.t % tScanlineWidth;
34
/*    
35
    static int iLastLine = 0;
36
    if ( iLastLine > iRayLine )
37
    {
38
        printf("\nNew Frame Begin\n");
39
        __debugbreak();
40
    }
41
    iLastLine = iRayLine;
42
    printf("%d->%d %d %d\n", OldVideoMode, NewVideoMode, iRayLine, iRayOffset);
43
*/
44
 
45
    if (OldVideoMode == 3 || NewVideoMode == 3)
46
    {
47
        // ������������ ��/� sinclair ����� �� ����� �������� �������� ��������
48
        // (�� ������ AlCo ���� ������ ���������)
49
        for(unsigned y = 0; y < 200; y++)
50
        {
51
            AtmVideoCtrl.Scanlines[y+56].VideoMode = NewVideoMode;
796 DimkaM 52
            AtmVideoCtrl.Scanlines[y+56].Offset = int(((y & ~7U) << 3) + 0x01C0);
716 lvd 53
        }
54
        return;
55
    }
56
 
57
    if (OldVideoMode != 6 && NewVideoMode != 6)
58
    {
59
        // ��� ���������� ������ ������������ ����� ��������� ������� � ������������ ������������.
60
        // ���������� ������ ��� �� ��, �� ����� ������������. 
61
        // �������������, ��� � �������� ��������.
62
 
63
        // �������������� ����� ���������� �� �������������� ���������
64
        if (iRayOffset >= tEachBorderWidth)
65
            ++iRayLine;
66
 
67
        while (iRayLine < 256)
68
        {
69
            AtmVideoCtrl.Scanlines[iRayLine++].VideoMode = NewVideoMode;
70
        }
71
//        printf("%d->%d SKIPPED!\n",  OldVideoMode, NewVideoMode);
72
        return;
73
    }
74
 
75
    //
76
    // ������������ � ���������:
77
    // ����� �������� 312 ���������, �� 224����� (noturbo) � ������.
78
    //
79
    //  "������" - ������� 3 ���� ������ �������������� ����������������� (�����) ���������
80
    //  "�����"  - ������� ����� � �����������, � �������� �������� ����� ���������������
81
    //             ����� �������� � �������������� +8 ��� +64
82
    //  "�����"  - ��������� ��������. �� ���� ������ �������� "��������".
83
    //             ������� �������: 
84
    //          ������ � ����� �� ������: 56 ���������
85
    //              ����� � ������ �� ������: 32 ����� (64�������).
86
    // 
87
    // +64 ����������, ����� CROW 1->0, �� ����:
88
    //  ���� � ��������� ��� �������� �� ������ 7 �� ������ 0,
89
    //  ���� ��� ������������ ��������->������� ��� ������ A5=0,
90
    //  ���� ��� ������������ �������->�������� ��� ������ A5=1 � ������ 0..3
91
    //
92
    // +8 ���������� �� ������ � ����� 64-����� �������� (������ 32�����) ���������� �� ������
93
    // (�����: +8 �� ���������� ������ A3..A5 � ���������� ������� �������� � �������.)
94
    //
95
    // ����� A3..A5 (����������� +8) ����������, ����� RCOL 1->0, �� ����:
96
    //  ���� � ��������� ��� �������� � ������ �� ������,
97
    //  ���� �� ������� ��� ������������ �������->��������
98
    //
99
 
100
 
101
    if (iRayLine >= 256)
102
    {
103
        return;
104
    }
105
 
106
    // ������� ������ ������� ��������� (���������� ���������� � ������)
107
    int Offset = AtmVideoCtrl.Scanlines[iRayLine].Offset;
108
 
109
    // �������� �������� ����������, � ������ ����������� ��� ��������� ������.
110
    // ����� ���������, ���� ��������� +64 ���������� ��� ������������ �����������:
111
    //  - ���� ��� �� ������� ������ �� ������ ��� �� ������� ����� �� ������ - �������� ������ ��� ������� ���������
112
    //  - ���� ��� �� ������ ��� �� ������� ������ �� ������ - �������� ������ ��� ��������� ���������
113
    if ( iRayLine < iLinesAboveBorder || iRayOffset < tEachBorderWidth )
114
    {
115
        // ��� �� �������. ���� ������ �� ������, ���� ����� �� ������.
116
        // ��� ��������� ��������� � ������� ���������.
117
 
118
        // ���������� ������������ �����������.
119
        if ( NewVideoMode == 6 )
120
        {
121
            // ������������ � ��������� �����.
796 DimkaM 122
            if ( (Offset & 32) // �������� ������� "��� ������ A5=1"
123
                 && (iRayLine & 7) < 4 // �������� ������� "� ������ 0..3"
716 lvd 124
               )
125
            {
126
//                printf("CASE-1: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
127
                Offset += 64;
128
                AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
129
            }
130
 
131
            AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
132
 
133
            // ����� ������� ���� ����� ������ ������� ��������� � ��������� ������ ����� �������� A3..A5
134
            Offset &= (~0x38); // ����� A3..A5
135
//            printf("CASE-1a, reset A3..A5: 0x%.4x\n", Offset);
136
 
137
            // ������� ������������ ��� ���������� ���������
138
            while (++iRayLine < 256)
139
            {
140
                if ( 0 == (iRayLine & 7))
141
                {
142
                    Offset += 64;
143
                }
144
                AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
145
                AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
146
            }
147
        } else {
148
            // ������������ �� ���������� ������.
796 DimkaM 149
            if ( 0 == (Offset & 32) ) // �������� ������� "��� ������ A5=0"
716 lvd 150
            {
151
//                printf("CASE-2: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
152
                Offset += 64;
153
                AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
154
            }
155
            AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
156
 
157
            // ������� ������������ ��� ���������� ���������
158
            while (++iRayLine < 256)
159
            {
160
                AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
161
                AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
162
            }
163
        }
164
    } else {
165
        // ��� ������ �����, ���� ������ ������ �� ������.
166
 
167
        // ��������� ������� �������� �����������
168
 
169
        // ���������� � ����������� ��� +64 ����������, 
170
        // ��������� � ���� ��������� ������ ������ ���������
171
        if (iRayLine == AtmVideoCtrl.CurrentRayLine)
172
        {
173
            Offset += AtmVideoCtrl.IncCounter_InRaster;
174
        } else {
175
            // ������� ����������� ������� (�.�. �������� �� ��������� �������� �� �������)
176
            // �������������� ��� ��� ������� ���������.
177
            AtmVideoCtrl.CurrentRayLine = iRayLine;
178
            AtmVideoCtrl.IncCounter_InRaster = 0;
179
            AtmVideoCtrl.IncCounter_InBorder = 0;
180
        }
181
 
182
        // ���������� � ����������� ��� +8 ����������, ������������ ��� ��������� ������
183
        bool bRayInRaster = iRayOffset < (tScreenWidth + tEachBorderWidth);
184
 
796 DimkaM 185
        int iScanlineRemainder = 0; // ������� +8 ����������� ��� ����� ������� �� ����� ��������� 
716 lvd 186
                                    //  (�.�. ��� ����� ������������ �����������)
187
        if ( bRayInRaster )
188
        {
189
            // ��� ������ �����. 
190
            // ���������� � �������� ����������� ������� +8, 
191
            // ������� ���� ��������� ������������ 64���������� �����.
192
            int iIncValue = 8 * ((iRayOffset-tEachBorderWidth)/32);
193
            iScanlineRemainder = 40 - iIncValue;
194
//            printf("CASE-4: 0x%.4x Incremented (+%d) on line %d\n", Offset, iIncValue, iRayLine);
195
            Offset += iIncValue;
196
        } else {
197
            // ��������� ������ ����� ���������.
198
            // �.�. ��� 5-��� 64-���������� ����� ���� ��������. ���������� � ������ +40.
199
//            printf("CASE-5: 0x%.4x Incremented (+40) on line %d\n", Offset, iRayLine);
200
            Offset += 40;
201
 
202
            // ���� ���������� ������� ��� ��������� �����,
203
            // �� ��� �������� � ������ �� ������ ������ ���� �������� A3..A5
204
            if (OldVideoMode == 6)
205
            {
206
                Offset &= (~0x38); // ����� A3..A5
207
//                printf("CASE-5a, reset A3..A5: 0x%.4x\n", Offset);
208
            }
209
        }
210
 
211
        // ���������� � ����������� ��� +64 ����������, 
212
        // ��������� � ���� ��������� ������� �� ������� ������ ���������
213
        Offset += AtmVideoCtrl.IncCounter_InBorder;
214
 
215
        // ������� �������� ����������� ���������. 
216
        // ������������ ������������ �����������.
217
        int OffsetInc = 0;
218
        if ( NewVideoMode == 6 )
219
        {
220
            // ������������ � ��������� �����.
796 DimkaM 221
            if ( (Offset & 32) // �������� ������� "��� ������ A5=1"
222
                && (iRayLine & 7) < 4 // �������� ������� "� ������ 0..3"
716 lvd 223
                )
224
            {
225
                OffsetInc = 64;
226
//                printf("CASE-6: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
227
                Offset += OffsetInc;
228
            }
229
            // ������� ������������ ��� ���������� ���������
230
            Offset += iScanlineRemainder;
231
            while (++iRayLine < 256)
232
            {
233
                if ( 0 == (iRayLine & 7))
234
                    Offset += 64;
235
                AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
236
                AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
237
            }
238
        } else {
239
            // ������������ �� ���������� ������.
796 DimkaM 240
            if ( 0 == (Offset & 32) ) // �������� ������� "��� ������ A5=0"
716 lvd 241
            {
242
                OffsetInc = 64;
243
//                printf("CASE-7: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
244
                Offset += OffsetInc;
245
            }
246
 
247
            // ������� ������������ ��� ���������� ���������
248
            Offset += iScanlineRemainder;
249
            while (++iRayLine < 256)
250
            {
251
                AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
252
                AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
253
                Offset += 40;
254
            }
255
        }
256
 
257
        // ���������� ��������� ��������� �� ������, 
258
        // ���� �� ����� ��������� � ���� ��������� ������� ���������.
259
        if ( bRayInRaster )
260
        {
261
            AtmVideoCtrl.IncCounter_InRaster += OffsetInc;
262
        } else {
263
            AtmVideoCtrl.IncCounter_InBorder += OffsetInc;
264
        }
265
    }
266
}
267
 
268
void set_atm_FF77(unsigned port, unsigned char val)
269
{
270
   if ((comp.pFF77 ^ val) & 1)
271
       atm_memswap();
272
 
273
 
274
   if ((comp.pFF77 & 7) ^ (val & 7))
275
   {
276
        // ���������� ������������ �����������
277
        AtmApplySideEffectsWhenChangeVideomode(val);
278
   }
279
 
280
   comp.pFF77 = val;
281
   comp.aFF77 = port;
282
   cpu.int_gate = (comp.pFF77 & 0x20) != false;
283
   set_banks();
284
}
285
 
286
void set_atm_aFE(unsigned char addr)
287
{
288
   unsigned char old_aFE = comp.aFE;
289
   comp.aFE = addr;
290
   if ((addr ^ old_aFE) & 0x40) atm_memswap();
291
   if ((addr ^ old_aFE) & 0x80) set_banks();
292
}
293
 
294
static u8 atm_pal[0x10] = { 0 };
295
 
296
void atm_writepal(unsigned char val)
297
{
298
   assert(comp.border_attr < 0x10);
299
   atm_pal[comp.border_attr] = val;
796 DimkaM 300
 
301
   // �������������� ������� � ������ ULA+
302
   u8 PalIdx = ((comp.border_attr & 8) << 1) | (comp.border_attr & 7);
303
   comp.comp_pal[PalIdx + 0*8] =
304
   comp.comp_pal[PalIdx + 1*8] =
305
   comp.comp_pal[PalIdx + 3*8] =
306
   comp.comp_pal[PalIdx + 5*8] = u8(t.atm_pal_map[val]);
716 lvd 307
   temp.comp_pal_changed = 1;
308
}
309
 
310
u8 atm_readpal()
311
{
312
   return atm_pal[comp.border_attr];
313
}
314
 
315
unsigned char atm450_z(unsigned t)
316
{
317
   // PAL hardware gives 3 zeros in secret short time intervals
318
   if (conf.frame < 80000) { // NORMAL SPEED mode
319
      if ((unsigned)(t-7200) < 40 || (unsigned)(t-7284) < 40 || (unsigned)(t-7326) < 40) return 0;
320
   } else { // TURBO mode
321
      if ((unsigned)(t-21514) < 40 || (unsigned)(t-21703) < 80 || (unsigned)(t-21808) < 40) return 0;
322
   }
323
   return 0x80;
324
}