~ubuntu-branches/ubuntu/feisty/fpc/feisty

« back to all changes in this revision

Viewing changes to rtl/go32v2/vesa.inc

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2007-01-27 20:08:50 UTC
  • mfrom: (1.2.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070127200850-9mrptaqqjsx9nwa7
Tags: 2.0.4-5
* Fixed Build-Depends.
* Add myself to Uploaders in debian/control.
* Make sure that the sources are really patched before building them.
* Build unit 'libc' on powerpc too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
{
2
 
    $Id: vesa.inc,v 1.12 2005/02/14 17:13:22 peter Exp $
3
 
    This file is part of the Free Pascal run time library.
4
 
    Copyright (c) 1999-2000 by Carl Eric Codere
5
 
 
6
 
    This include implements VESA basic access.
7
 
 
8
 
    See the file COPYING.FPC, included in this distribution,
9
 
    for details about the copyright.
10
 
 
11
 
    This program is distributed in the hope that it will be useful,
12
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
 
15
 
 **********************************************************************}
16
 
type
17
 
 
18
 
  palrec = packed record              { record used for set/get DAC palette }
19
 
       blue, green, red, align: byte;
20
 
  end;
21
 
 
22
 
const
23
 
  { VESA attributes     }
24
 
  attrSwitchDAC        = $01;    { DAC is switchable           (1.2)   }
25
 
  attrNotVGACompatible = $02;    { Video is NOT VGA compatible (2.0)   }
26
 
  attrSnowCheck        = $04;    { Video must use snow checking(2.0)   }
27
 
 
28
 
  { mode attribute bits }
29
 
  modeAvail          = $01;      { Hardware supports this mode (1.0)   }
30
 
  modeExtendInfo     = $02;      { Extended information        (1.0)   }
31
 
  modeBIOSSupport    = $04;      { TTY BIOS Support            (1.0)   }
32
 
  modeColor          = $08;      { This is a color mode        (1.0)   }
33
 
  modeGraphics       = $10;      { This is a graphics mode     (1.0)   }
34
 
  modeNotVGACompatible = $20;    { this mode is NOT I/O VGA compatible (2.0)}
35
 
  modeNoWindowed     = $40;      { This mode does not support Windows (2.0) }
36
 
  modeLinearBuffer   = $80;      { This mode supports linear buffers  (2.0) }
37
 
 
38
 
  { window attributes }
39
 
  winSupported       = $01;
40
 
  winReadable        = $02;
41
 
  winWritable        = $04;
42
 
 
43
 
  { memory model }
44
 
  modelText          = $00;
45
 
  modelCGA           = $01;
46
 
  modelHerc          = $02;
47
 
  model4plane        = $03;
48
 
  modelPacked        = $04;
49
 
  modelModeX         = $05;
50
 
  modelRGB           = $06;
51
 
  modelYUV           = $07;
52
 
 
53
 
{$ifndef dpmi}
54
 
{$i vesah.inc}
55
 
{ otherwise it's already included in graph.pp }
56
 
{$endif dpmi}
57
 
 
58
 
var
59
 
 
60
 
  BytesPerLine: word;              { Number of bytes per scanline }
61
 
  YOffset : word;                  { Pixel offset for VESA page flipping }
62
 
 
63
 
  { window management }
64
 
  ReadWindow : byte;      { Window number for reading. }
65
 
  WriteWindow: byte;      { Window number for writing. }
66
 
  winReadSeg : word;      { Address of segment for read  }
67
 
  winWriteSeg: word;      { Address of segment for writes}
68
 
  CurrentReadBank : integer; { active read bank          }
69
 
  CurrentWriteBank: integer; { active write bank         }
70
 
 
71
 
  BankShift : word;       { address to shift by when switching banks. }
72
 
 
73
 
  { linear mode specific stuff }
74
 
  InLinear  : boolean;    { true if in linear mode }
75
 
  LinearPageOfs : longint; { offset used to set active page }
76
 
  FrameBufferLinearAddress : longint;
77
 
 
78
 
  ScanLines: word;        { maximum number of scan lines for mode }
79
 
 
80
 
function hexstr(val : longint;cnt : byte) : string;
81
 
const
82
 
  HexTbl : array[0..15] of char='0123456789ABCDEF';
83
 
var
84
 
  i : longint;
85
 
begin
86
 
  hexstr[0]:=char(cnt);
87
 
  for i:=cnt downto 1 do
88
 
   begin
89
 
     hexstr[i]:=hextbl[val and $f];
90
 
     val:=val shr 4;
91
 
   end;
92
 
end;
93
 
 
94
 
 
95
 
{$IFDEF DPMI}
96
 
 
97
 
  function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
98
 
   var
99
 
    ptrlong : longint;
100
 
    VESAPtr : ^TVESAInfo;
101
 
    st : string[4];
102
 
    regs : TDPMIRegisters;
103
 
{$ifndef fpc}
104
 
    ModeSel: word;
105
 
    offs: longint;
106
 
{$endif fpc}
107
 
    { added... }
108
 
    modelist: PmodeList;
109
 
    i: longint;
110
 
    RealSeg : word;
111
 
   begin
112
 
    { Allocate real mode buffer }
113
 
{$ifndef fpc}
114
 
    Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
115
 
    { Get selector value }
116
 
    VESAPtr := pointer(Ptrlong shl 16);
117
 
{$else fpc}
118
 
    Ptrlong:=Global_Dos_Alloc(sizeof(TVESAInfo));
119
 
    New(VESAPtr);
120
 
{$endif fpc}
121
 
    { Get segment value }
122
 
    RealSeg := word(Ptrlong shr 16);
123
 
    if not assigned(VESAPtr) then
124
 
      RunError(203);
125
 
    FillChar(regs, sizeof(regs), #0);
126
 
 
127
 
    { Get VESA Mode information ... }
128
 
    regs.eax := $4f00;
129
 
    regs.es := RealSeg;
130
 
    regs.edi := $00;
131
 
    RealIntr($10, regs);
132
 
{$ifdef fpc}
133
 
   { no far pointer support in FPC yet, so move the vesa info into a memory }
134
 
   { block in the DS slector space (JM)                                     }
135
 
    dosmemget(RealSeg,0,VesaPtr^,SizeOf(TVESAInfo));
136
 
{$endif fpc}
137
 
    St:=Vesaptr^.signature;
138
 
    if st<>'VESA' then
139
 
     begin
140
 
{$ifdef logging}
141
 
         LogLn('No VESA detected.');
142
 
{$endif logging}
143
 
         getVesaInfo := FALSE;
144
 
{$ifndef fpc}
145
 
         GlobalDosFree(word(PtrLong and $ffff));
146
 
{$else fpc}
147
 
         If not Global_Dos_Free(word(PtrLong and $ffff)) then
148
 
           RunError(216);
149
 
         { also free the extra allocated buffer }
150
 
         Dispose(VESAPtr);
151
 
{$endif fpc}
152
 
         exit;
153
 
     end
154
 
    else
155
 
      getVesaInfo := TRUE;
156
 
 
157
 
{$ifndef fpc}
158
 
    { The mode pointer buffer points to a real mode memory }
159
 
    { Therefore steps to get the modes:                    }
160
 
    {  1. Allocate Selector and SetLimit to max number of  }
161
 
    {     of possible modes.                               }
162
 
    ModeSel := AllocSelector(0);
163
 
    SetSelectorLimit(ModeSel, 256*sizeof(word));
164
 
 
165
 
    {  2. Set Selector linear address to the real mode pointer }
166
 
    {     returned.                                            }
167
 
    offs := longint(longint(VESAPtr^.ModeList) shr 16) shl 4;
168
 
   {shouldn't the OR in the next line be a + ?? (JM)}
169
 
    offs :=  offs OR (Longint(VESAPtr^.ModeList) and $ffff);
170
 
    SetSelectorBase(ModeSel, offs);
171
 
 
172
 
     { copy VESA mode information to a protected mode buffer and }
173
 
     { then free the real mode buffer...                         }
174
 
     Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
175
 
     GlobalDosFree(word(PtrLong and $ffff));
176
 
 
177
 
    { ModeList points to the mode list     }
178
 
    { We must copy it somewhere...         }
179
 
    ModeList := Ptr(ModeSel, 0);
180
 
 
181
 
{$else fpc}
182
 
    { No far pointer support, so the Ptr(ModeSel, 0) doesn't work.     }
183
 
    { Immediately copy everything to a buffer in the DS selector space }
184
 
     New(ModeList);
185
 
    { The following may copy data from outside the VESA buffer, but it   }
186
 
    { shouldn't get past the 1MB limit, since that would mean the buffer }
187
 
    { has been allocated in the BIOS or high memory region, which seems  }
188
 
    { impossible to me (JM)}
189
 
     DosMemGet(word(longint(VESAPtr^.ModeList) shr 16),
190
 
        word(longint(VESAPtr^.ModeList) and $ffff), ModeList^,256*sizeof(word));
191
 
 
192
 
     { copy VESA mode information to a protected mode buffer and }
193
 
     { then free the real mode buffer...                         }
194
 
     Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
195
 
     If not Global_Dos_Free(word(PtrLong and $ffff)) then
196
 
       RunError(216);
197
 
     Dispose(VESAPtr);
198
 
{$endif fpc}
199
 
 
200
 
    i:=0;
201
 
    new(VESAInfo.ModeList);
202
 
    while ModeList^[i]<> $ffff do
203
 
     begin
204
 
{$ifdef logging}
205
 
      LogLn('Found mode $'+hexstr(ModeList^[i],4));
206
 
{$endif loggin}
207
 
      VESAInfo.ModeList^[i] := ModeList^[i];
208
 
      Inc(i);
209
 
     end;
210
 
    VESAInfo.ModeList^[i]:=$ffff;
211
 
    { Free the temporary selector used to get mode information }
212
 
{$ifdef logging}
213
 
    LogLn(strf(i) + ' modes found.');
214
 
{$endif logging}
215
 
{$ifndef fpc}
216
 
    FreeSelector(ModeSel);
217
 
{$else fpc}
218
 
    Dispose(ModeList);
219
 
{$endif fpc}
220
 
   end;
221
 
 
222
 
  function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
223
 
   var
224
 
    Ptr: longint;
225
 
{$ifndef fpc}
226
 
    VESAPtr : ^TVESAModeInfo;
227
 
{$endif fpc}
228
 
    regs : TDPMIRegisters;
229
 
    RealSeg: word;
230
 
   begin
231
 
    { Alllocate real mode buffer }
232
 
{$ifndef fpc}
233
 
    Ptr:=GlobalDosAlloc(sizeof(TVESAModeInfo));
234
 
    { get the selector value }
235
 
    VESAPtr := pointer(longint(Ptr shl 16));
236
 
    if not assigned(VESAPtr) then
237
 
      RunError(203);
238
 
{$else fpc}
239
 
    Ptr:=Global_Dos_Alloc(sizeof(TVESAModeInfo));
240
 
{$endif fpc}
241
 
    { get the segment value }
242
 
    RealSeg := word(Ptr shr 16);
243
 
    { setup interrupt registers }
244
 
    FillChar(regs, sizeof(regs), #0);
245
 
    { call VESA mode information...}
246
 
    regs.eax := $4f01;
247
 
    regs.es := RealSeg;
248
 
    regs.edi := $00;
249
 
    regs.ecx := mode;
250
 
    RealIntr($10, regs);
251
 
    if word(regs.eax) <> $4f then
252
 
      getVESAModeInfo := FALSE
253
 
    else
254
 
      getVESAModeInfo := TRUE;
255
 
    { copy to protected mode buffer ... }
256
 
{$ifndef fpc}
257
 
    Move(VESAPtr^, ModeInfo, sizeof(ModeInfo));
258
 
{$else fpc}
259
 
    DosMemGet(RealSeg,0,ModeInfo,sizeof(ModeInfo));
260
 
{$endif fpc}
261
 
    { free real mode memory  }
262
 
{$ifndef fpc}
263
 
    GlobalDosFree(Word(Ptr and $ffff));
264
 
{$else fpc}
265
 
    If not Global_Dos_Free(Word(Ptr and $ffff)) then
266
 
      RunError(216);
267
 
{$endif fpc}
268
 
   end;
269
 
 
270
 
{$ELSE}
271
 
  function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
272
 
  asm
273
 
       mov ax,4F00h
274
 
       les di,VESAInfo
275
 
       int 10h
276
 
       sub ax,004Fh  {make sure we got 004Fh back}
277
 
       cmp ax,1
278
 
       sbb al,al
279
 
       cmp word ptr es:[di],'V'or('E'shl 8)  {signature should be 'VESA'}
280
 
       jne @@ERR
281
 
       cmp word ptr es:[di+2],'S'or('A'shl 8)
282
 
       je @@X
283
 
     @@ERR:
284
 
       mov al,0
285
 
     @@X:
286
 
  end;
287
 
 
288
 
 
289
 
  function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
290
 
   asm
291
 
     mov ax,4F01h
292
 
     mov cx,mode
293
 
     les di,ModeInfo
294
 
     int 10h
295
 
     sub ax,004Fh   {make sure it's 004Fh}
296
 
     cmp ax,1
297
 
     sbb al,al
298
 
   end;
299
 
 
300
 
{$ENDIF}
301
 
 
302
 
  function SearchVESAModes(mode: Word): boolean;
303
 
  {********************************************************}
304
 
  { Searches for a specific DEFINED vesa mode. If the mode }
305
 
  { is not available for some reason, then returns FALSE   }
306
 
  { otherwise returns TRUE.                                }
307
 
  {********************************************************}
308
 
   var
309
 
     i: word;
310
 
     ModeSupported : Boolean;
311
 
    begin
312
 
      i:=0;
313
 
      { let's assume it's not available ... }
314
 
      ModeSupported := FALSE;
315
 
      { This is a STUB VESA implementation  }
316
 
      if VESAInfo.ModeList^[0] = $FFFF then exit;
317
 
      repeat
318
 
        if VESAInfo.ModeList^[i] = mode then
319
 
         begin
320
 
            { we found it, the card supports this mode... }
321
 
            ModeSupported := TRUE;
322
 
            break;
323
 
         end;
324
 
        Inc(i);
325
 
      until VESAInfo.ModeList^[i] = $ffff;
326
 
      { now check if the hardware supports it... }
327
 
      If ModeSupported then
328
 
        begin
329
 
          { we have to init everything to zero, since VBE < 1.1  }
330
 
          { may not setup fields correctly.                      }
331
 
          FillChar(VESAModeInfo, sizeof(VESAModeInfo), #0);
332
 
          If GetVESAModeInfo(VESAModeInfo, Mode) And
333
 
             ((VESAModeInfo.attr and modeAvail) <> 0) then
334
 
            ModeSupported := TRUE
335
 
          else
336
 
            ModeSupported := FALSE;
337
 
        end;
338
 
       SearchVESAModes := ModeSupported;
339
 
    end;
340
 
 
341
 
 
342
 
 
343
 
  procedure SetBankIndex(win: byte; BankNr: Integer); assembler;
344
 
   asm
345
 
{$IFDEF REGCALL}
346
 
     mov  bl, al
347
 
{$ELSE REGCALL}
348
 
     mov  bl,[Win]
349
 
{$ENDIF REGCALL}
350
 
     mov  ax,4f05h
351
 
     mov  bh,00h
352
 
{$IFNDEF REGCALL}
353
 
     mov  dx,[BankNr]
354
 
{$ENDIF REGCALL}
355
 
{$ifdef fpc}
356
 
     push ebp
357
 
{$endif fpc}
358
 
     int  10h
359
 
{$ifdef fpc}
360
 
     pop ebp
361
 
{$endif fpc}
362
 
   end;
363
 
 
364
 
  {********************************************************}
365
 
  { There are two routines for setting banks. This may in  }
366
 
  { in some cases optimize a bit some operations, if the   }
367
 
  { hardware supports it, because one window is used for   }
368
 
  { reading and one window is used for writing.            }
369
 
  {********************************************************}
370
 
  procedure SetReadBank(BankNr: Integer);
371
 
   begin
372
 
     { check if this is the current bank... if so do nothing. }
373
 
     if BankNr = CurrentReadBank then exit;
374
 
{$ifdef logging}
375
 
{     LogLn('Setting read bank to '+strf(BankNr));}
376
 
{$endif logging}
377
 
     CurrentReadBank := BankNr;          { save current bank number     }
378
 
     BankNr := BankNr shl BankShift;     { adjust to window granularity }
379
 
     { we set both banks, since one may read only }
380
 
     SetBankIndex(ReadWindow, BankNr);
381
 
     { if the hardware supports only one window }
382
 
     { then there is only one single bank, so   }
383
 
     { update both bank numbers.                }
384
 
     if ReadWindow = WriteWindow then
385
 
       CurrentWriteBank := CurrentReadBank;
386
 
   end;
387
 
 
388
 
  procedure SetWriteBank(BankNr: Integer);
389
 
   begin
390
 
     { check if this is the current bank... if so do nothing. }
391
 
     if BankNr = CurrentWriteBank then exit;
392
 
{$ifdef logging}
393
 
{     LogLn('Setting write bank to '+strf(BankNr));}
394
 
{$endif logging}
395
 
     CurrentWriteBank := BankNr;          { save current bank number     }
396
 
     BankNr := BankNr shl BankShift;     { adjust to window granularity }
397
 
     { we set both banks, since one may read only }
398
 
     SetBankIndex(WriteWindow, BankNr);
399
 
     { if the hardware supports only one window }
400
 
     { then there is only one single bank, so   }
401
 
     { update both bank numbers.                }
402
 
     if ReadWindow = WriteWindow then
403
 
       CurrentReadBank := CurrentWriteBank;
404
 
   end;
405
 
 
406
 
 {************************************************************************}
407
 
 {*                     8-bit pixels VESA mode routines                  *}
408
 
 {************************************************************************}
409
 
 
410
 
  procedure PutPixVESA256(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
411
 
  var
412
 
     offs : longint;
413
 
  begin
414
 
     X:= X + StartXViewPort;
415
 
     Y:= Y + StartYViewPort;
416
 
     { convert to absolute coordinates and then verify clipping...}
417
 
     if ClipPixels then
418
 
     Begin
419
 
       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
420
 
         exit;
421
 
       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
422
 
         exit;
423
 
     end;
424
 
     Y := Y + YOffset; { adjust pixel for correct virtual page }
425
 
     offs := longint(y) * BytesPerLine + x;
426
 
       begin
427
 
         SetWriteBank(integer(offs shr 16));
428
 
         mem[WinWriteSeg : word(offs)] := byte(color);
429
 
       end;
430
 
  end;
431
 
 
432
 
  procedure DirectPutPixVESA256(x, y : integer); {$ifndef fpc}far;{$endif fpc}
433
 
  var
434
 
     offs : longint;
435
 
     col : byte;
436
 
  begin
437
 
     offs := (longint(y) + YOffset) * BytesPerLine + x;
438
 
     Case CurrentWriteMode of
439
 
       XorPut:
440
 
         Begin
441
 
           SetReadBank(integer(offs shr 16));
442
 
           col := mem[WinReadSeg : word(offs)] xor byte(CurrentColor);
443
 
         End;
444
 
       AndPut:
445
 
         Begin
446
 
           SetReadBank(integer(offs shr 16));
447
 
           col := mem[WinReadSeg : word(offs)] And byte(CurrentColor);
448
 
         End;
449
 
       OrPut:
450
 
         Begin
451
 
           SetReadBank(integer(offs shr 16));
452
 
           col := mem[WinReadSeg : word(offs)] or byte(currentcolor);
453
 
         End
454
 
       else
455
 
         Begin
456
 
           If CurrentWriteMode <> NotPut then
457
 
             col := Byte(CurrentColor)
458
 
           else col := Not(Byte(CurrentColor));
459
 
         End
460
 
     End;
461
 
     SetWriteBank(integer(offs shr 16));
462
 
     mem[WinWriteSeg : word(offs)] := Col;
463
 
  end;
464
 
 
465
 
  function GetPixVESA256(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
466
 
  var
467
 
     offs : longint;
468
 
  begin
469
 
     X:= X + StartXViewPort;
470
 
     Y:= Y + StartYViewPort + YOffset;
471
 
     offs := longint(y) * BytesPerLine + x;
472
 
     SetReadBank(integer(offs shr 16));
473
 
     GetPixVESA256:=mem[WinReadSeg : word(offs)];
474
 
  end;
475
 
 
476
 
  Procedure GetScanLineVESA256(x1, x2, y: integer; var data); {$ifndef fpc}far;{$endif}
477
 
  var offs: Longint;
478
 
      l, amount, bankrest, index, pixels: longint;
479
 
      curbank: integer;
480
 
  begin
481
 
    inc(x1,StartXViewPort);
482
 
    inc(x2,StartXViewPort);
483
 
    {$ifdef logging}
484
 
    LogLn('getscanline256 '+strf(x1)+' - '+strf(x2)+' at '+strf(y+StartYViewPort));
485
 
    {$endif logging}
486
 
    index := 0;
487
 
    amount := x2-x1+1;
488
 
    Offs:=(Longint(y)+StartYViewPort+YOffset)*bytesperline+x1;
489
 
    Repeat
490
 
      curbank := integer(offs shr 16);
491
 
      SetReadBank(curbank);
492
 
      {$ifdef logging}
493
 
      LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
494
 
      {$endif logging}
495
 
      If ((amount >= 4) and
496
 
          ((offs and 3) = 0)) or
497
 
         (amount >= 4+4-(offs and 3)) Then
498
 
      { allign target }
499
 
        Begin
500
 
          If (offs and 3) <> 0 then
501
 
          { this cannot go past a window boundary bacause the }
502
 
          { size of a window is always a multiple of 4        }
503
 
            Begin
504
 
              {$ifdef logging}
505
 
              LogLn('Alligning by reading '+strf(4-(offs and 3))+' pixels');
506
 
              {$endif logging}
507
 
              for l := 1 to 4-(offs and 3) do
508
 
                WordArray(Data)[index+l-1] :=
509
 
                  Mem[WinReadSeg:word(offs)+l-1];
510
 
              inc(index, l);
511
 
              inc(offs, l);
512
 
              dec(amount, l);
513
 
            End;
514
 
          {$ifdef logging}
515
 
          LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
516
 
          {$endif logging}
517
 
          { offs is now 4-bytes alligned }
518
 
          If amount <= ($10000-(Offs and $ffff)) Then
519
 
             bankrest := amount
520
 
          else {the rest won't fit anymore in the current window }
521
 
            bankrest := $10000 - (Offs and $ffff);
522
 
          { it is possible that by aligning, we ended up in a new }
523
 
          { bank, so set the correct bank again to make sure      }
524
 
          setreadbank(offs shr 16);
525
 
          {$ifdef logging}
526
 
          LogLn('Rest to be read from this window: '+strf(bankrest));
527
 
          {$endif logging}
528
 
          For l := 0 to (Bankrest div 4)-1 Do
529
 
            begin
530
 
              pixels := MemL[WinWriteSeg:word(offs)+l*4];
531
 
              WordArray(Data)[index+l*4] := pixels and $ff;
532
 
              pixels := pixels shr 8;
533
 
              WordArray(Data)[index+l*4+1] := pixels and $ff;
534
 
              pixels := pixels shr 8;
535
 
              WordArray(Data)[index+l*4+2] := pixels and $ff;
536
 
              pixels := pixels shr 8;
537
 
              WordArray(Data)[index+l*4+3] := pixels{ and $ff};
538
 
            end;
539
 
          inc(index,l*4+4);
540
 
          inc(offs,l*4+4);
541
 
          dec(amount,l*4+4);
542
 
          {$ifdef logging}
543
 
          LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
544
 
          {$endif logging}
545
 
        End
546
 
      Else
547
 
        Begin
548
 
          {$ifdef logging}
549
 
          LogLn('Leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
550
 
          {$endif logging}
551
 
          For l := 0 to amount - 1 do
552
 
            begin
553
 
              { this may cross a bank at any time, so adjust          }
554
 
              { because this loop alwys runs for very little pixels,  }
555
 
              { there's little gained by splitting it up              }
556
 
              setreadbank(offs shr 16);
557
 
              WordArray(Data)[index+l] := mem[WinReadSeg:word(offs)];
558
 
              inc(offs);
559
 
            end;
560
 
          amount := 0
561
 
        End
562
 
    Until amount = 0;
563
 
  end;
564
 
 
565
 
  procedure HLineVESA256(x,x2,y: integer); {$ifndef fpc}far;{$endif fpc}
566
 
 
567
 
   var Offs: Longint;
568
 
       mask, l, bankrest: longint;
569
 
       curbank, hlength: integer;
570
 
   Begin
571
 
    { must we swap the values? }
572
 
    if x > x2 then
573
 
      Begin
574
 
        x := x xor x2;
575
 
        x2 := x xor x2;
576
 
        x:= x xor x2;
577
 
      end;
578
 
    { First convert to global coordinates }
579
 
    X   := X + StartXViewPort;
580
 
    X2  := X2 + StartXViewPort;
581
 
    Y   := Y + StartYViewPort;
582
 
    if ClipPixels then
583
 
      Begin
584
 
         if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
585
 
                StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
586
 
            exit;
587
 
      end;
588
 
    {$ifdef logging2}
589
 
    LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode));
590
 
    {$endif logging2}
591
 
    HLength := x2 - x + 1;
592
 
    {$ifdef logging2}
593
 
    LogLn('length: '+strf(hlength));
594
 
    {$endif logging2}
595
 
    if HLength>0 then
596
 
      begin
597
 
         Offs:=(Longint(y)+YOffset)*bytesperline+x;
598
 
         {$ifdef logging2}
599
 
         LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
600
 
         {$endif logging2}
601
 
         Mask := byte(CurrentColor)+byte(CurrentColor) shl 8;
602
 
         Mask := Mask + Mask shl 16;
603
 
         Case CurrentWriteMode of
604
 
           AndPut:
605
 
             Begin
606
 
               Repeat
607
 
                 curbank := integer(offs shr 16);
608
 
                 SetWriteBank(curbank);
609
 
                 SetReadBank(curbank);
610
 
                 {$ifdef logging2}
611
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
612
 
                 {$endif logging2}
613
 
                 If ((HLength >= 4) and
614
 
                     ((offs and 3) = 0)) or
615
 
                    (HLength >= 4+4-(offs and 3)) Then
616
 
                 { align target }
617
 
                   Begin
618
 
                     l := 0;
619
 
                     If (offs and 3) <> 0 then
620
 
                     { this cannot go past a window boundary bacause the }
621
 
                     { size of a window is always a multiple of 4        }
622
 
                       Begin
623
 
                         {$ifdef logging2}
624
 
                         LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
625
 
                         {$endif logging2}
626
 
                         for l := 1 to 4-(offs and 3) do
627
 
                           Mem[WinWriteSeg:word(offs)+l-1] :=
628
 
                             Mem[WinReadSeg:word(offs)+l-1] And Byte(CurrentColor);
629
 
                       End;
630
 
                     Dec(HLength, l);
631
 
                     inc(offs, l);
632
 
                     {$ifdef logging2}
633
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
634
 
                     {$endif logging}
635
 
                     { offs is now 4-bytes alligned }
636
 
                     If HLength <= ($10000-(Offs and $ffff)) Then
637
 
                        bankrest := HLength
638
 
                     else {the rest won't fit anymore in the current window }
639
 
                       bankrest := $10000 - (Offs and $ffff);
640
 
                     { it is possible that by aligningm we ended up in a new }
641
 
                     { bank, so set the correct bank again to make sure      }
642
 
                     setwritebank(offs shr 16);
643
 
                     setreadbank(offs shr 16);
644
 
                     {$ifdef logging2}
645
 
                     LogLn('Rest to be drawn in this window: '+strf(bankrest));
646
 
                     {$endif logging}
647
 
                     For l := 0 to (Bankrest div 4)-1 Do
648
 
                       MemL[WinWriteSeg:word(offs)+l*4] :=
649
 
                         MemL[WinReadSeg:word(offs)+l*4] And Mask;
650
 
                     inc(offs,l*4+4);
651
 
                     dec(hlength,l*4+4);
652
 
                     {$ifdef logging2}
653
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
654
 
                     {$endif logging}
655
 
                   End
656
 
                 Else
657
 
                   Begin
658
 
                     {$ifdef logging2}
659
 
                     LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
660
 
                     {$endif logging}
661
 
                     For l := 0 to HLength - 1 do
662
 
                       begin
663
 
                         { this may cross a bank at any time, so adjust          }
664
 
                         { becauese this loop alwys runs for very little pixels, }
665
 
                         { there's little gained by splitting it up              }
666
 
                         setreadbank(offs shr 16);
667
 
                         setwritebank(offs shr 16);
668
 
                         Mem[WinWriteSeg:word(offs)] :=
669
 
                           Mem[WinReadSeg:word(offs)] And byte(currentColor);
670
 
                         inc(offs);
671
 
                       end;
672
 
                     HLength := 0
673
 
                   End
674
 
               Until HLength = 0;
675
 
             End;
676
 
           XorPut:
677
 
             Begin
678
 
               Repeat
679
 
                 curbank := integer(offs shr 16);
680
 
                 SetWriteBank(curbank);
681
 
                 SetReadBank(curbank);
682
 
                 {$ifdef logging2}
683
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
684
 
                 {$endif logging}
685
 
                 If ((HLength >= 4) and
686
 
                     ((offs and 3) = 0)) or
687
 
                    (HLength >= 4+4-(offs and 3)) Then
688
 
                 { allign target }
689
 
                   Begin
690
 
                     l := 0;
691
 
                     If (offs and 3) <> 0 then
692
 
                     { this cannot go past a window boundary bacause the }
693
 
                     { size of a window is always a multiple of 4        }
694
 
                       Begin
695
 
                         {$ifdef logging2}
696
 
                         LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
697
 
                         {$endif logging}
698
 
                         for l := 1 to 4-(offs and 3) do
699
 
                           Mem[WinWriteSeg:word(offs)+l-1] :=
700
 
                             Mem[WinReadSeg:word(offs)+l-1] Xor Byte(CurrentColor);
701
 
                       End;
702
 
                     Dec(HLength, l);
703
 
                     inc(offs, l);
704
 
                     {$ifdef logging2}
705
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
706
 
                     {$endif logging}
707
 
                     { offs is now 4-bytes alligned }
708
 
                     If HLength <= ($10000-(Offs and $ffff)) Then
709
 
                        bankrest := HLength
710
 
                     else {the rest won't fit anymore in the current window }
711
 
                       bankrest := $10000 - (Offs and $ffff);
712
 
                     { it is possible that by aligningm we ended up in a new }
713
 
                     { bank, so set the correct bank again to make sure      }
714
 
                     setwritebank(offs shr 16);
715
 
                     setreadbank(offs shr 16);
716
 
                     {$ifdef logging2}
717
 
                     LogLn('Rest to be drawn in this window: '+strf(bankrest));
718
 
                     {$endif logging}
719
 
                     For l := 0 to (Bankrest div 4)-1 Do
720
 
                       MemL[WinWriteSeg:word(offs)+l*4] :=
721
 
                         MemL[WinReadSeg:word(offs)+l*4] Xor Mask;
722
 
                     inc(offs,l*4+4);
723
 
                     dec(hlength,l*4+4);
724
 
                     {$ifdef logging2}
725
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
726
 
                     {$endif logging}
727
 
                   End
728
 
                 Else
729
 
                   Begin
730
 
                     {$ifdef logging2}
731
 
                     LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
732
 
                     {$endif logging}
733
 
                     For l := 0 to HLength - 1 do
734
 
                       begin
735
 
                         { this may cross a bank at any time, so adjust          }
736
 
                         { because this loop alwys runs for very little pixels,  }
737
 
                         { there's little gained by splitting it up              }
738
 
                         setreadbank(offs shr 16);
739
 
                         setwritebank(offs shr 16);
740
 
                         Mem[WinWriteSeg:word(offs)] :=
741
 
                           Mem[WinReadSeg:word(offs)] xor byte(currentColor);
742
 
                         inc(offs);
743
 
                       end;
744
 
                     HLength := 0
745
 
                   End
746
 
               Until HLength = 0;
747
 
             End;
748
 
           OrPut:
749
 
             Begin
750
 
               Repeat
751
 
                 curbank := integer(offs shr 16);
752
 
                 SetWriteBank(curbank);
753
 
                 SetReadBank(curbank);
754
 
                 {$ifdef logging2}
755
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
756
 
                 {$endif logging}
757
 
                 If ((HLength >= 4) and
758
 
                     ((offs and 3) = 0)) or
759
 
                    (HLength >= 4+4-(offs and 3)) Then
760
 
                 { allign target }
761
 
                   Begin
762
 
                     l := 0;
763
 
                     If (offs and 3) <> 0 then
764
 
                     { this cannot go past a window boundary bacause the }
765
 
                     { size of a window is always a multiple of 4        }
766
 
                       Begin
767
 
                         {$ifdef logging2}
768
 
                         LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
769
 
                         {$endif logging}
770
 
                         for l := 1 to 4-(offs and 3) do
771
 
                           Mem[WinWriteSeg:word(offs)+l-1] :=
772
 
                             Mem[WinReadSeg:word(offs)+l-1] Or Byte(CurrentColor);
773
 
                       End;
774
 
                     Dec(HLength, l);
775
 
                     inc(offs, l);
776
 
                     { it is possible that by aligningm we ended up in a new }
777
 
                     { bank, so set the correct bank again to make sure      }
778
 
                     setwritebank(offs shr 16);
779
 
                     setreadbank(offs shr 16);
780
 
                     {$ifdef logging2}
781
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
782
 
                     {$endif logging}
783
 
                     { offs is now 4-bytes alligned }
784
 
                     If HLength <= ($10000-(Offs and $ffff)) Then
785
 
                        bankrest := HLength
786
 
                     else {the rest won't fit anymore in the current window }
787
 
                       bankrest := $10000 - (Offs and $ffff);
788
 
                     {$ifdef logging2}
789
 
                     LogLn('Rest to be drawn in this window: '+strf(bankrest));
790
 
                     {$endif logging}
791
 
                     For l := 0 to (Bankrest div 4)-1 Do
792
 
                       MemL[WinWriteSeg:offs+l*4] :=
793
 
                         MemL[WinReadSeg:word(offs)+l*4] Or Mask;
794
 
                     inc(offs,l*4+4);
795
 
                     dec(hlength,l*4+4);
796
 
                     {$ifdef logging2}
797
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
798
 
                     {$endif logging}
799
 
                   End
800
 
                 Else
801
 
                   Begin
802
 
                     {$ifdef logging2}
803
 
                     LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
804
 
                     {$endif logging}
805
 
                     For l := 0 to HLength - 1 do
806
 
                       begin
807
 
                         { this may cross a bank at any time, so adjust          }
808
 
                         { because this loop alwys runs for very little pixels,  }
809
 
                         { there's little gained by splitting it up              }
810
 
                         setreadbank(offs shr 16);
811
 
                         setwritebank(offs shr 16);
812
 
                         Mem[WinWriteSeg:word(offs)] :=
813
 
                           Mem[WinReadSeg:word(offs)] And byte(currentColor);
814
 
                         inc(offs);
815
 
                       end;
816
 
                     HLength := 0
817
 
                   End
818
 
               Until HLength = 0;
819
 
             End
820
 
           Else
821
 
             Begin
822
 
               If CurrentWriteMode = NotPut Then
823
 
                 Mask := Not(Mask);
824
 
               Repeat
825
 
                 curbank := integer(offs shr 16);
826
 
                 SetWriteBank(curbank);
827
 
                 {$ifdef logging2}
828
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)+' -- '+strf(offs));
829
 
                 {$endif logging}
830
 
                 If ((HLength >= 4) and
831
 
                     ((offs and 3) = 0)) or
832
 
                    (HLength >= 4+4-(offs and 3)) Then
833
 
                 { allign target }
834
 
                   Begin
835
 
                     l := 0;
836
 
                     If (offs and 3) <> 0 then
837
 
                     { this cannot go past a window boundary bacause the }
838
 
                     { size of a window is always a multiple of 4        }
839
 
                       Begin
840
 
                         {$ifdef logging2}
841
 
                         LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
842
 
                         {$endif logging}
843
 
                         for l := 1 to 4-(offs and 3) do
844
 
                           Mem[WinWriteSeg:word(offs)+l-1] := Byte(Mask);
845
 
                       End;
846
 
                     Dec(HLength, l);
847
 
                     inc(offs, l);
848
 
                     {$ifdef logging2}
849
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
850
 
                     {$endif logging}
851
 
                     { offs is now 4-bytes alligned }
852
 
                     If HLength <= ($10000-(Offs and $ffff)) Then
853
 
                        bankrest := HLength
854
 
                     else {the rest won't fit anymore in the current window }
855
 
                       bankrest := $10000 - (Offs and $ffff);
856
 
                     { it is possible that by aligningm we ended up in a new }
857
 
                     { bank, so set the correct bank again to make sure      }
858
 
                     setwritebank(offs shr 16);
859
 
                     {$ifdef logging2}
860
 
                     LogLn('Rest to be drawn in this window: '+strf(bankrest)+' -- '+hexstr(bankrest,8));
861
 
                     {$endif logging}
862
 
                     For l := 0 to (Bankrest div 4)-1 Do
863
 
                       MemL[WinWriteSeg:word(offs)+l*4] := Mask;
864
 
                     inc(offs,l*4+4);
865
 
                     dec(hlength,l*4+4);
866
 
                     {$ifdef logging2}
867
 
                     LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
868
 
                     {$endif logging}
869
 
                   End
870
 
                 Else
871
 
                   Begin
872
 
                     {$ifdef logging2}
873
 
                     LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
874
 
                     {$endif logging}
875
 
                     For l := 0 to HLength - 1 do
876
 
                       begin
877
 
                         { this may cross a bank at any time, so adjust          }
878
 
                         { because this loop alwys runs for very little pixels,  }
879
 
                         { there's little gained by splitting it up              }
880
 
                         setwritebank(offs shr 16);
881
 
                         Mem[WinWriteSeg:word(offs)] := byte(mask);
882
 
                         inc(offs);
883
 
                       end;
884
 
                     HLength := 0
885
 
                   End
886
 
               Until HLength = 0;
887
 
             End;
888
 
         End;
889
 
       end;
890
 
   end;
891
 
 
892
 
  procedure VLineVESA256(x,y,y2: integer); {$ifndef fpc}far;{$endif fpc}
893
 
 
894
 
   var Offs: Longint;
895
 
       l, bankrest: longint;
896
 
       curbank, vlength: integer;
897
 
       col: byte;
898
 
   Begin
899
 
    { must we swap the values? }
900
 
    if y > y2 then
901
 
      Begin
902
 
        y := y xor y2;
903
 
        y2 := y xor y2;
904
 
        y:= y xor y2;
905
 
      end;
906
 
    { First convert to global coordinates }
907
 
    X   := X + StartXViewPort;
908
 
    Y   := Y + StartYViewPort;
909
 
    Y2  := Y2 + StartYViewPort;
910
 
    if ClipPixels then
911
 
      Begin
912
 
         if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
913
 
                StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
914
 
            exit;
915
 
      end;
916
 
    Col := Byte(CurrentColor);
917
 
    {$ifdef logging2}
918
 
    LogLn('vline '+strf(y)+' - '+strf(y2)+' on '+strf(x)+' in mode '+strf(currentwritemode));
919
 
    {$endif logging}
920
 
    VLength := y2 - y + 1;
921
 
    {$ifdef logging2}
922
 
    LogLn('length: '+strf(vlength));
923
 
    {$endif logging}
924
 
    if VLength>0 then
925
 
      begin
926
 
         Offs:=(Longint(y)+YOffset)*bytesperline+x;
927
 
         {$ifdef logging2}
928
 
         LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
929
 
         {$endif logging}
930
 
         Case CurrentWriteMode of
931
 
           AndPut:
932
 
             Begin
933
 
               Repeat
934
 
                 curbank := integer(offs shr 16);
935
 
                 SetWriteBank(curbank);
936
 
                 SetReadBank(curbank);
937
 
                 {$ifdef logging2}
938
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
939
 
                 {$endif logging}
940
 
                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
941
 
                   bankrest := VLength
942
 
                 else {the rest won't fit anymore in the current window }
943
 
                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
944
 
                 {$ifdef logging2}
945
 
                 LogLn('Rest to be drawn in this window: '+strf(bankrest));
946
 
                 {$endif logging}
947
 
                 For l := 0 to Bankrest-1 Do
948
 
                   begin
949
 
                     Mem[WinWriteSeg:word(offs)] :=
950
 
                       Mem[WinReadSeg:word(offs)] And Col;
951
 
                     inc(offs,bytesperline);
952
 
                   end;
953
 
                 dec(VLength,l+1);
954
 
                 {$ifdef logging2}
955
 
                 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
956
 
                 {$endif logging}
957
 
               Until VLength = 0;
958
 
             End;
959
 
           XorPut:
960
 
             Begin
961
 
               Repeat
962
 
                 curbank := integer(offs shr 16);
963
 
                 SetWriteBank(curbank);
964
 
                 SetReadBank(curbank);
965
 
                 {$ifdef logging2}
966
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
967
 
                 {$endif logging}
968
 
                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
969
 
                   bankrest := VLength
970
 
                 else {the rest won't fit anymore in the current window }
971
 
                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
972
 
                 {$ifdef logging2}
973
 
                 LogLn('Rest to be drawn in this window: '+strf(bankrest));
974
 
                 {$endif logging}
975
 
                 For l := 0 to Bankrest-1 Do
976
 
                   begin
977
 
                     Mem[WinWriteSeg:word(offs)] :=
978
 
                       Mem[WinReadSeg:word(offs)] Xor Col;
979
 
                     inc(offs,bytesperline);
980
 
                   end;
981
 
                 dec(VLength,l+1);
982
 
                 {$ifdef logging2}
983
 
                 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
984
 
                 {$endif logging}
985
 
               Until VLength = 0;
986
 
             End;
987
 
           OrPut:
988
 
             Begin
989
 
               Repeat
990
 
                 curbank := integer(offs shr 16);
991
 
                 SetWriteBank(curbank);
992
 
                 SetReadBank(curbank);
993
 
                 {$ifdef logging2}
994
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
995
 
                 {$endif logging}
996
 
                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
997
 
                   bankrest := VLength
998
 
                 else {the rest won't fit anymore in the current window }
999
 
                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
1000
 
                 {$ifdef logging2}
1001
 
                 LogLn('Rest to be drawn in this window: '+strf(bankrest));
1002
 
                 {$endif logging}
1003
 
                 For l := 0 to Bankrest-1 Do
1004
 
                   begin
1005
 
                     Mem[WinWriteSeg:word(offs)] :=
1006
 
                       Mem[WinReadSeg:word(offs)] Or Col;
1007
 
                     inc(offs,bytesperline);
1008
 
                   end;
1009
 
                 dec(VLength,l+1);
1010
 
                 {$ifdef logging2}
1011
 
                 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
1012
 
                 {$endif logging}
1013
 
               Until VLength = 0;
1014
 
             End;
1015
 
           Else
1016
 
             Begin
1017
 
               If CurrentWriteMode = NotPut Then
1018
 
                 Col := Not(Col);
1019
 
               Repeat
1020
 
                 curbank := integer(offs shr 16);
1021
 
                 SetWriteBank(curbank);
1022
 
                 {$ifdef logging2}
1023
 
                 LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
1024
 
                 {$endif logging}
1025
 
                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
1026
 
                   bankrest := VLength
1027
 
                 else {the rest won't fit anymore in the current window }
1028
 
                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
1029
 
                 {$ifdef logging2}
1030
 
                 LogLn('Rest to be drawn in this window: '+strf(bankrest));
1031
 
                 {$endif logging}
1032
 
                 For l := 0 to Bankrest-1 Do
1033
 
                   begin
1034
 
                     Mem[WinWriteSeg:word(offs)] := Col;
1035
 
                     inc(offs,bytesperline);
1036
 
                   end;
1037
 
                 dec(VLength,l+1);
1038
 
                 {$ifdef logging2}
1039
 
                 LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
1040
 
                 {$endif logging}
1041
 
               Until VLength = 0;
1042
 
             End;
1043
 
         End;
1044
 
       end;
1045
 
   end;
1046
 
 
1047
 
  procedure PatternLineVESA256(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
1048
 
  {********************************************************}
1049
 
  { Draws a horizontal patterned line according to the     }
1050
 
  { current Fill Settings.                                 }
1051
 
  {********************************************************}
1052
 
  { Important notes:                                       }
1053
 
  {  - CurrentColor must be set correctly before entering  }
1054
 
  {    this routine.                                       }
1055
 
  {********************************************************}
1056
 
   type
1057
 
     TVESA256Fill = Record
1058
 
       case byte of
1059
 
         0: (data1, data2: longint);
1060
 
         1: (pat: array[0..7] of byte);
1061
 
     end;
1062
 
 
1063
 
   var
1064
 
    fill: TVESA256Fill;
1065
 
    bankrest, l : longint;
1066
 
    offs, amount: longint;
1067
 
    i           : smallint;
1068
 
    j           : smallint;
1069
 
    OldWriteMode : word;
1070
 
    TmpFillPattern, patternPos : byte;
1071
 
   begin
1072
 
     { convert to global coordinates ... }
1073
 
     x1 := x1 + StartXViewPort;
1074
 
     x2 := x2 + StartXViewPort;
1075
 
     y  := y + StartYViewPort;
1076
 
     { if line was fully clipped then exit...}
1077
 
     if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort,
1078
 
        StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
1079
 
         exit;
1080
 
     OldWriteMode := CurrentWriteMode;
1081
 
     CurrentWriteMode := NormalPut;
1082
 
     { Get the current pattern }
1083
 
     TmpFillPattern := FillPatternTable
1084
 
       [FillSettings.Pattern][((y + startYViewPort) and $7)+1];
1085
 
     {$ifdef logging2}
1086
 
     LogLn('patternline '+strf(x1)+' - '+strf(x2)+' on '+strf(y));
1087
 
     {$endif logging2}
1088
 
     { how long is the line }
1089
 
     amount := x2 - x1 + 1;
1090
 
     { offset to start at }
1091
 
     offs := (longint(y)+yoffset)*bytesperline+x1;
1092
 
     { convert the pattern data into the actual color sequence }
1093
 
     j := 1;
1094
 
     FillChar(fill,sizeOf(fill),byte(currentBkColor));
1095
 
     for i := 0 to 7 do
1096
 
       begin
1097
 
         if TmpFillPattern and j <> 0 then
1098
 
           fill.pat[7-i] := currentColor;
1099
 
{$ifopt q+}
1100
 
{$q-}
1101
 
{$define overflowOn}
1102
 
{$endif}
1103
 
         j := j shl 1;
1104
 
{$ifdef overflowOn}
1105
 
{$q+}
1106
 
{$undef overflowOn}
1107
 
{$endif}
1108
 
       end;
1109
 
     Repeat
1110
 
       SetWriteBank(integer(offs shr 16));
1111
 
       If (amount > 7) and
1112
 
          (((offs and 7) = 0) or
1113
 
           (amount > 7+8-(offs and 7))) Then
1114
 
         Begin
1115
 
           { align target }
1116
 
           l := 0;
1117
 
           If (offs and 7) <> 0 then
1118
 
           { this cannot go past a window boundary bacause the }
1119
 
           { size of a window is always a multiple of 8        }
1120
 
             Begin
1121
 
               { position in the pattern where to start }
1122
 
               patternPos := offs and 7;
1123
 
               {$ifdef logging2}
1124
 
               LogLn('Aligning by drawing '+strf(8-(offs and 7))+' pixels');
1125
 
               {$endif logging2}
1126
 
               for l := 1 to 8-(offs and 7) do
1127
 
                 begin
1128
 
                   Mem[WinWriteSeg:word(offs)+l-1] := fill.pat[patternPos and 7];
1129
 
                   inc(patternPos)
1130
 
                 end;
1131
 
             End;
1132
 
           Dec(amount, l);
1133
 
           inc(offs, l);
1134
 
           {$ifdef logging2}
1135
 
           LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
1136
 
           {$endif logging2}
1137
 
           { offs is now 8-bytes alligned }
1138
 
           If amount <= ($10000-(Offs and $ffff)) Then
1139
 
              bankrest := amount
1140
 
           else {the rest won't fit anymore in the current window }
1141
 
             bankrest := $10000 - (Offs and $ffff);
1142
 
           { it is possible that by aligningm we ended up in a new }
1143
 
           { bank, so set the correct bank again to make sure      }
1144
 
           setwritebank(offs shr 16);
1145
 
           {$ifdef logging2}
1146
 
           LogLn('Rest to be drawn in this window: '+strf(bankrest));
1147
 
           {$endif logging2}
1148
 
           for l := 0 to (bankrest div 8)-1 Do
1149
 
             begin
1150
 
               MemL[WinWriteSeg:word(offs)+l*8] := fill.data1;
1151
 
               MemL[WinWriteSeg:word(offs)+l*8+4] := fill.data2;
1152
 
             end;
1153
 
           inc(offs,l*8+8);
1154
 
           dec(amount,l*8+8);
1155
 
           {$ifdef logging2}
1156
 
           LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
1157
 
           {$endif logging2}
1158
 
         End
1159
 
       Else
1160
 
         Begin
1161
 
           {$ifdef logging2}
1162
 
           LogLn('Drawing leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
1163
 
           {$endif logging2}
1164
 
           patternPos := offs and 7;
1165
 
           For l := 0 to amount - 1 do
1166
 
             begin
1167
 
               { this may cross a bank at any time, so adjust          }
1168
 
               { because this loop alwys runs for very little pixels,  }
1169
 
               { there's little gained by splitting it up              }
1170
 
               setwritebank(offs shr 16);
1171
 
               Mem[WinWriteSeg:word(offs)] := fill.pat[patternPos and 7];
1172
 
               inc(offs);
1173
 
               inc(patternPos);
1174
 
             end;
1175
 
           amount := 0;
1176
 
         End
1177
 
     Until amount = 0;
1178
 
     currentWriteMode := oldWriteMode;
1179
 
   end;
1180
 
 
1181
 
 
1182
 
 {************************************************************************}
1183
 
 {*                    256 colors VESA mode routines  Linear mode        *}
1184
 
 {************************************************************************}
1185
 
{$ifdef FPC}
1186
 
type
1187
 
  pbyte = ^byte;
1188
 
  pword = ^word;
1189
 
 
1190
 
  procedure DirectPutPixVESA256Linear(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1191
 
  var
1192
 
     offs : longint;
1193
 
     col : byte;
1194
 
  begin
1195
 
     offs := longint(y) * BytesPerLine + x;
1196
 
     Case CurrentWriteMode of
1197
 
       XorPut:
1198
 
         Begin
1199
 
           if UseNoSelector then
1200
 
             col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1201
 
           else
1202
 
             seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1203
 
           col := col xor byte(CurrentColor);
1204
 
         End;
1205
 
       AndPut:
1206
 
         Begin
1207
 
           if UseNoSelector then
1208
 
             col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1209
 
           else
1210
 
             seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1211
 
           col := col and byte(CurrentColor);
1212
 
         End;
1213
 
       OrPut:
1214
 
         Begin
1215
 
           if UseNoSelector then
1216
 
             col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1217
 
           else
1218
 
             seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1219
 
           col := col or byte(CurrentColor);
1220
 
         End
1221
 
       else
1222
 
         Begin
1223
 
           If CurrentWriteMode <> NotPut then
1224
 
             col := Byte(CurrentColor)
1225
 
           else col := Not(Byte(CurrentColor));
1226
 
         End
1227
 
     End;
1228
 
     if UseNoSelector then
1229
 
       pbyte(LFBPointer+offs+LinearPageOfs)^:=col
1230
 
     else
1231
 
       seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,1);
1232
 
  end;
1233
 
 
1234
 
  procedure PutPixVESA256Linear(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1235
 
  var
1236
 
     offs : longint;
1237
 
  begin
1238
 
     X:= X + StartXViewPort;
1239
 
     Y:= Y + StartYViewPort;
1240
 
     { convert to absolute coordinates and then verify clipping...}
1241
 
     if ClipPixels then
1242
 
     Begin
1243
 
       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1244
 
         exit;
1245
 
       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1246
 
         exit;
1247
 
     end;
1248
 
     offs := longint(y) * BytesPerLine + x;
1249
 
     {$ifdef logging}
1250
 
     logln('putpix offset: '+hexstr(offs,8)+', color: '+strf(color)+', lpo: $'+
1251
 
       hexstr(LinearPageOfs,8));
1252
 
     {$endif logging}
1253
 
     if UseNoSelector then
1254
 
       pbyte(LFBPointer+offs+LinearPageOfs)^:=byte(color)
1255
 
     else
1256
 
       seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,1);
1257
 
  end;
1258
 
 
1259
 
  function GetPixVESA256Linear(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
1260
 
  var
1261
 
     offs : longint;
1262
 
     col : byte;
1263
 
  begin
1264
 
     X:= X + StartXViewPort;
1265
 
     Y:= Y + StartYViewPort;
1266
 
     offs := longint(y) * BytesPerLine + x;
1267
 
     {$ifdef logging}
1268
 
     logln('getpix offset: '+hexstr(offs,8)+', lpo: $'+
1269
 
       hexstr(LinearPageOfs,8));
1270
 
     {$endif logging}
1271
 
     if UseNoSelector then
1272
 
       col:=pbyte(LFBPointer+offs+LinearPageOfs)^
1273
 
     else
1274
 
       seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
1275
 
     GetPixVESA256Linear:=col;
1276
 
  end;
1277
 
(*
1278
 
function SetVESADisplayStart(PageNum : word;x,y : integer):Boolean;
1279
 
var
1280
 
  dregs : registers;
1281
 
begin
1282
 
  if PageNum>VesaModeInfo.NumberOfPages then
1283
 
    PageNum:=0;
1284
 
{$ifdef DEBUG}
1285
 
  if PageNum>0 then
1286
 
    writeln(stderr,'Setting Display Page ',PageNum);
1287
 
{$endif DEBUG}
1288
 
  dregs.RealEBX:=0{ $80 for Wait for retrace };
1289
 
  dregs.RealECX:=x;
1290
 
  dregs.RealEDX:=y+PageNum*maxy;
1291
 
  dregs.RealSP:=0;
1292
 
  dregs.RealSS:=0;
1293
 
  dregs.RealEAX:=$4F07; RealIntr($10,dregs);
1294
 
  { idem as above !!! }
1295
 
  if (dregs.RealEAX and $1FF) <> $4F then
1296
 
    begin
1297
 
{$ifdef DEBUG}
1298
 
       writeln(stderr,'Set Display start error');
1299
 
{$endif DEBUG}
1300
 
       SetVESADisplayStart:=false;
1301
 
    end
1302
 
  else
1303
 
    SetVESADisplayStart:=true;
1304
 
end;
1305
 
*)
1306
 
{$endif FPC}
1307
 
 
1308
 
 
1309
 
 {************************************************************************}
1310
 
 {*                    15/16bit pixels VESA mode routines                *}
1311
 
 {************************************************************************}
1312
 
 
1313
 
  procedure PutPixVESA32kOr64k(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1314
 
  var
1315
 
     offs : longint;
1316
 
  begin
1317
 
{$ifdef logging}
1318
 
     logln('putpixvesa32kor64k('+strf(x)+','+strf(y)+')');
1319
 
{$endif logging}
1320
 
     X:= X + StartXViewPort;
1321
 
     Y:= Y + StartYViewPort;
1322
 
     { convert to absolute coordinates and then verify clipping...}
1323
 
     if ClipPixels then
1324
 
     Begin
1325
 
       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1326
 
         exit;
1327
 
       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1328
 
         exit;
1329
 
     end;
1330
 
     Y := Y + YOffset; { adjust pixel for correct virtual page }
1331
 
     offs := longint(y) * BytesPerLine + 2*x;
1332
 
     SetWriteBank(integer(offs shr 16));
1333
 
{$ifdef logging}
1334
 
     logln('putpixvesa32kor64k offset: '+strf(word(offs)));
1335
 
{$endif logging}
1336
 
     memW[WinWriteSeg : word(offs)] := color;
1337
 
  end;
1338
 
 
1339
 
  function GetPixVESA32kOr64k(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
1340
 
  var
1341
 
     offs : longint;
1342
 
  begin
1343
 
     X:= X + StartXViewPort;
1344
 
     Y:= Y + StartYViewPort + YOffset;
1345
 
     offs := longint(y) * BytesPerLine + 2*x;
1346
 
     SetReadBank(integer(offs shr 16));
1347
 
     GetPixVESA32kOr64k:=memW[WinReadSeg : word(offs)];
1348
 
  end;
1349
 
 
1350
 
  procedure DirectPutPixVESA32kOr64k(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1351
 
  var
1352
 
     offs : longint;
1353
 
     col : word;
1354
 
  begin
1355
 
{$ifdef logging}
1356
 
     logln('directputpixvesa32kor64k('+strf(x)+','+strf(y)+')');
1357
 
{$endif logging}
1358
 
     y:= Y + YOffset;
1359
 
     offs := longint(y) * BytesPerLine + 2*x;
1360
 
     SetWriteBank(integer((offs shr 16) and $ff));
1361
 
     Case CurrentWriteMode of
1362
 
       XorPut:
1363
 
         Begin
1364
 
           SetReadBank(integer(offs shr 16));
1365
 
           memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] xor currentcolor;
1366
 
         End;
1367
 
       AndPut:
1368
 
         Begin
1369
 
           SetReadBank(integer(offs shr 16));
1370
 
           memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] And currentcolor;
1371
 
         End;
1372
 
       OrPut:
1373
 
         Begin
1374
 
           SetReadBank(integer(offs shr 16));
1375
 
           memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] or currentcolor;
1376
 
         End
1377
 
       else
1378
 
         Begin
1379
 
           If CurrentWriteMode <> NotPut Then
1380
 
             col := CurrentColor
1381
 
           Else col := Not(CurrentColor);
1382
 
{$ifdef logging}
1383
 
           logln('directputpixvesa32kor64k offset: '+strf(word(offs)));
1384
 
{$endif logging}
1385
 
           memW[WinWriteSeg : word(offs)] := Col;
1386
 
         End
1387
 
     End;
1388
 
  end;
1389
 
 
1390
 
{$ifdef FPC}
1391
 
 {************************************************************************}
1392
 
 {*                    15/16bit pixels VESA mode routines  Linear mode   *}
1393
 
 {************************************************************************}
1394
 
 
1395
 
  procedure PutPixVESA32kor64kLinear(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1396
 
  var
1397
 
     offs : longint;
1398
 
  begin
1399
 
     X:= X + StartXViewPort;
1400
 
     Y:= Y + StartYViewPort;
1401
 
     { convert to absolute coordinates and then verify clipping...}
1402
 
     if ClipPixels then
1403
 
     Begin
1404
 
       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1405
 
         exit;
1406
 
       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1407
 
         exit;
1408
 
     end;
1409
 
     offs := longint(y) * BytesPerLine + 2*x;
1410
 
     if UseNoSelector then
1411
 
       pword(LFBPointer+offs+LinearPageOfs)^:=color
1412
 
     else
1413
 
       seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,2);
1414
 
  end;
1415
 
 
1416
 
  function GetPixVESA32kor64kLinear(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
1417
 
  var
1418
 
     offs : longint;
1419
 
     color : word;
1420
 
  begin
1421
 
     X:= X + StartXViewPort;
1422
 
     Y:= Y + StartYViewPort;
1423
 
     offs := longint(y) * BytesPerLine + 2*x;
1424
 
     if UseNoSelector then
1425
 
       color:=pword(LFBPointer+offs+LinearPageOfs)^
1426
 
     else
1427
 
       seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@color),2);
1428
 
     GetPixVESA32kor64kLinear:=color;
1429
 
  end;
1430
 
 
1431
 
  procedure DirectPutPixVESA32kor64kLinear(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1432
 
  var
1433
 
     offs : longint;
1434
 
     col : word;
1435
 
  begin
1436
 
     offs := longint(y) * BytesPerLine + 2*x;
1437
 
     Case CurrentWriteMode of
1438
 
       XorPut:
1439
 
         Begin
1440
 
           if UseNoSelector then
1441
 
             col:=pword(LFBPointer+offs+LinearPageOfs)^
1442
 
           else
1443
 
             seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
1444
 
           col := col xor currentcolor;
1445
 
         End;
1446
 
       AndPut:
1447
 
         Begin
1448
 
           if UseNoSelector then
1449
 
             col:=pword(LFBPointer+offs+LinearPageOfs)^
1450
 
           else
1451
 
             seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
1452
 
           col := col and currentcolor;
1453
 
         End;
1454
 
       OrPut:
1455
 
         Begin
1456
 
           if UseNoSelector then
1457
 
             col:=pword(LFBPointer+offs+LinearPageOfs)^
1458
 
           else
1459
 
             seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
1460
 
           col := col or currentcolor;
1461
 
         End
1462
 
       else
1463
 
         Begin
1464
 
           If CurrentWriteMode <> NotPut Then
1465
 
             col := CurrentColor
1466
 
           Else col := Not(CurrentColor);
1467
 
         End
1468
 
     End;
1469
 
     if UseNoSelector then
1470
 
       pword(LFBPointer+offs+LinearPageOfs)^:=col
1471
 
     else
1472
 
       seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,2);
1473
 
  end;
1474
 
 
1475
 
{$endif FPC}
1476
 
 
1477
 
 {************************************************************************}
1478
 
 {*                     4-bit pixels VESA mode routines                  *}
1479
 
 {************************************************************************}
1480
 
 
1481
 
  procedure PutPixVESA16(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
1482
 
    var
1483
 
     offs : longint;
1484
 
     dummy : byte;
1485
 
  begin
1486
 
     X:= X + StartXViewPort;
1487
 
     Y:= Y + StartYViewPort;
1488
 
     { convert to absolute coordinates and then verify clipping...}
1489
 
    if ClipPixels then
1490
 
     Begin
1491
 
       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
1492
 
         exit;
1493
 
       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
1494
 
         exit;
1495
 
     end;
1496
 
     Y := Y + YOffset; { adjust pixel for correct virtual page }
1497
 
     { }
1498
 
     offs := longint(y) * BytesPerLine + (x div 8);
1499
 
     SetWriteBank(integer(offs shr 16));
1500
 
 
1501
 
     PortW[$3ce] := $0f01;       { Index 01 : Enable ops on all 4 planes }
1502
 
     PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
1503
 
 
1504
 
     Port[$3ce] := 8;           { Index 08 : Bitmask register.          }
1505
 
     Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
1506
 
 
1507
 
     dummy := Mem[WinWriteSeg: offs];  { Latch the data into host space.  }
1508
 
     Mem[WinWriteSeg: offs] := dummy;  { Write the data into video memory }
1509
 
     PortW[$3ce] := $ff08;         { Enable all bit planes.           }
1510
 
     PortW[$3ce] := $0001;         { Index 01 : Disable ops on all four planes.         }
1511
 
     { }
1512
 
  end;
1513
 
 
1514
 
 
1515
 
 Function GetPixVESA16(X,Y: Integer):word; {$ifndef fpc}far;{$endif fpc}
1516
 
 Var dummy, offset: Word;
1517
 
     shift: byte;
1518
 
  Begin
1519
 
    X:= X + StartXViewPort;
1520
 
    Y:= Y + StartYViewPort + YOffset;
1521
 
    offset := longint(Y) * BytesPerLine + (x div 8);
1522
 
    SetReadBank(integer(offset shr 16));
1523
 
    Port[$3ce] := 4;
1524
 
    shift := 7 - (X and 7);
1525
 
    Port[$3cf] := 0;
1526
 
    dummy := (Mem[WinReadSeg:offset] shr shift) and 1;
1527
 
    Port[$3cf] := 1;
1528
 
    dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 1);
1529
 
    Port[$3cf] := 2;
1530
 
    dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 2);
1531
 
    Port[$3cf] := 3;
1532
 
    dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 3);
1533
 
    GetPixVESA16 := dummy;
1534
 
  end;
1535
 
 
1536
 
 
1537
 
  procedure DirectPutPixVESA16(x, y : integer); {$ifndef fpc}far;{$endif fpc}
1538
 
    var
1539
 
     offs : longint;
1540
 
     dummy : byte;
1541
 
     Color : word;
1542
 
  begin
1543
 
    y:= Y + YOffset;
1544
 
    case CurrentWriteMode of
1545
 
      XORPut:
1546
 
        begin
1547
 
      { getpixel wants local/relative coordinates }
1548
 
          Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
1549
 
          Color := CurrentColor Xor Color;
1550
 
        end;
1551
 
      OrPut:
1552
 
        begin
1553
 
      { getpixel wants local/relative coordinates }
1554
 
          Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
1555
 
          Color := CurrentColor Or Color;
1556
 
        end;
1557
 
      AndPut:
1558
 
        begin
1559
 
      { getpixel wants local/relative coordinates }
1560
 
          Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
1561
 
          Color := CurrentColor And Color;
1562
 
        end;
1563
 
      NotPut:
1564
 
        begin
1565
 
          Color := Not Color;
1566
 
        end
1567
 
      else
1568
 
        Color := CurrentColor;
1569
 
    end;
1570
 
     offs := longint(y) * BytesPerLine + (x div 8);
1571
 
     SetWriteBank(integer(offs shr 16));
1572
 
     PortW[$3ce] := $0f01;       { Index 01 : Enable ops on all 4 planes }
1573
 
     PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
1574
 
 
1575
 
     Port[$3ce] := 8;           { Index 08 : Bitmask register.          }
1576
 
     Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
1577
 
 
1578
 
     dummy := Mem[WinWriteSeg: offs];  { Latch the data into host space.  }
1579
 
     Mem[WinWriteSeg: offs] := dummy;  { Write the data into video memory }
1580
 
     PortW[$3ce] := $ff08;         { Enable all bit planes.           }
1581
 
     PortW[$3ce] := $0001;         { Index 01 : Disable ops on all four planes.         }
1582
 
  end;
1583
 
 
1584
 
 
1585
 
 
1586
 
 
1587
 
 {************************************************************************}
1588
 
 {*                     VESA Palette entries                             *}
1589
 
 {************************************************************************}
1590
 
 
1591
 
 
1592
 
{$IFDEF DPMI}
1593
 
{$ifdef fpc}
1594
 
   Procedure SetVESARGBAllPalette(const Palette:PaletteType);
1595
 
    var
1596
 
     pal: array[0..255] of palrec;
1597
 
     regs: TDPMIRegisters;
1598
 
     c, Ptr: longint;
1599
 
     RealSeg: word;
1600
 
     FunctionNr : byte;   { use blankbit or normal RAMDAC programming? }
1601
 
    begin
1602
 
      if DirectColor then
1603
 
        Begin
1604
 
          _GraphResult := grError;
1605
 
          exit;
1606
 
        end;
1607
 
      { use the set/get palette function }
1608
 
      if VESAInfo.Version >= $0200 then
1609
 
        Begin
1610
 
          { check if blanking bit must be set when programming }
1611
 
          { the RAMDAC.                                        }
1612
 
          if (VESAInfo.caps and attrSnowCheck) <> 0 then
1613
 
            FunctionNr := $80
1614
 
          else
1615
 
            FunctionNr := $00;
1616
 
 
1617
 
          fillChar(pal,sizeof(pal),0);
1618
 
          { Convert to vesa format }
1619
 
          for c := 0 to 255 do
1620
 
            begin
1621
 
              pal[c].red := byte(palette.colors[c].red);
1622
 
              pal[c].green := byte(palette.colors[c].green);
1623
 
              pal[c].blue := byte(palette.colors[c].blue);
1624
 
            end;
1625
 
 
1626
 
        { Alllocate real mode buffer }
1627
 
          Ptr:=Global_Dos_Alloc(sizeof(pal));
1628
 
          {get the segment value}
1629
 
          RealSeg := word(Ptr shr 16);
1630
 
          { setup interrupt registers }
1631
 
          FillChar(regs, sizeof(regs), #0);
1632
 
          { copy palette values to real mode buffer }
1633
 
          DosMemPut(RealSeg,0,pal,sizeof(pal));
1634
 
          regs.eax := $4F09;
1635
 
          regs.ebx := FunctionNr;
1636
 
          regs.ecx := 256;
1637
 
          regs.edx := 0;
1638
 
          regs.es  := RealSeg;
1639
 
          regs.edi := 0;         { offset is always zero }
1640
 
          RealIntr($10, regs);
1641
 
 
1642
 
          { free real mode memory  }
1643
 
          If not Global_Dos_Free(word(Ptr and $ffff)) then
1644
 
            RunError(216);
1645
 
 
1646
 
          if word(regs.eax) <> $004F then
1647
 
            begin
1648
 
              _GraphResult := grError;
1649
 
              exit;
1650
 
            end;
1651
 
        end
1652
 
      else
1653
 
        { assume it's fully VGA compatible palette-wise. }
1654
 
        Begin
1655
 
          SetVGARGBAllPalette(palette);
1656
 
        end;
1657
 
      setallpalettedefault(palette);
1658
 
    end;
1659
 
{$endif fpc}
1660
 
 
1661
 
   Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
1662
 
      BlueValue : Integer);
1663
 
    var
1664
 
     pal: palrec;
1665
 
     regs: TDPMIRegisters;
1666
 
     Ptr: longint;
1667
 
{$ifndef fpc}
1668
 
     PalPtr : ^PalRec;
1669
 
{$endif fpc}
1670
 
     RealSeg: word;
1671
 
     FunctionNr : byte;   { use blankbit or normal RAMDAC programming? }
1672
 
    begin
1673
 
      if DirectColor then
1674
 
        Begin
1675
 
{$ifdef logging}
1676
 
          logln('setvesargbpalette called with directcolor = true');
1677
 
{$endif logging}
1678
 
          _GraphResult := grError;
1679
 
          exit;
1680
 
        end;
1681
 
        pal.align := 0;
1682
 
        pal.red := byte(RedValue) shr 2;
1683
 
        pal.green := byte(GreenValue) shr 2;
1684
 
        pal.blue := byte(BlueValue) shr 2;
1685
 
        { use the set/get palette function }
1686
 
        if VESAInfo.Version >= $0200 then
1687
 
          Begin
1688
 
            { check if blanking bit must be set when programming }
1689
 
            { the RAMDAC.                                        }
1690
 
            if (VESAInfo.caps and attrSnowCheck) <> 0 then
1691
 
              FunctionNr := $80
1692
 
            else
1693
 
              FunctionNr := $00;
1694
 
 
1695
 
            { Alllocate real mode buffer }
1696
 
{$ifndef fpc}
1697
 
            Ptr:=GlobalDosAlloc(sizeof(palrec));
1698
 
            { get the selector values }
1699
 
            PalPtr := pointer(Ptr shl 16);
1700
 
            if not assigned(PalPtr) then
1701
 
               RunError(203);
1702
 
{$else fpc}
1703
 
            Ptr:=Global_Dos_Alloc(sizeof(palrec));
1704
 
{$endif fpc}
1705
 
            {get the segment value}
1706
 
            RealSeg := word(Ptr shr 16);
1707
 
            { setup interrupt registers }
1708
 
            FillChar(regs, sizeof(regs), #0);
1709
 
            { copy palette values to real mode buffer }
1710
 
{$ifndef fpc}
1711
 
            move(pal, palptr^, sizeof(pal));
1712
 
{$else fpc}
1713
 
            DosMemPut(RealSeg,0,pal,sizeof(pal));
1714
 
{$endif fpc}
1715
 
            regs.eax := $4F09;
1716
 
            regs.ebx := FunctionNr;
1717
 
            regs.ecx := $01;
1718
 
            regs.edx := ColorNum;
1719
 
            regs.es  := RealSeg;
1720
 
            regs.edi := 0;         { offset is always zero }
1721
 
            RealIntr($10, regs);
1722
 
 
1723
 
            { free real mode memory  }
1724
 
{$ifndef fpc}
1725
 
            GlobalDosFree(word(Ptr and $ffff));
1726
 
{$else fpc}
1727
 
            If not Global_Dos_Free(word(Ptr and $ffff)) then
1728
 
              RunError(216);
1729
 
{$endif fpc}
1730
 
 
1731
 
            if word(regs.eax) <> $004F then
1732
 
              begin
1733
 
{$ifdef logging}
1734
 
                logln('setvesargbpalette failed while directcolor = false!');
1735
 
{$endif logging}
1736
 
                _GraphResult := grError;
1737
 
                exit;
1738
 
              end;
1739
 
          end
1740
 
        else
1741
 
          { assume it's fully VGA compatible palette-wise. }
1742
 
          Begin
1743
 
            SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1744
 
          end;
1745
 
    end;
1746
 
 
1747
 
 
1748
 
  Procedure GetVESARGBPalette(ColorNum: integer; Var
1749
 
      RedValue, GreenValue, BlueValue : integer);
1750
 
   var
1751
 
    pal: PalRec;
1752
 
{$ifndef fpc}
1753
 
    palptr : ^PalRec;
1754
 
{$endif fpc}
1755
 
    regs : TDPMIRegisters;
1756
 
    RealSeg: word;
1757
 
    ptr: longint;
1758
 
   begin
1759
 
      if DirectColor then
1760
 
        Begin
1761
 
{$ifdef logging}
1762
 
         logln('getvesargbpalette called with directcolor = true');
1763
 
{$endif logging}
1764
 
          _GraphResult := grError;
1765
 
          exit;
1766
 
        end;
1767
 
        { use the set/get palette function }
1768
 
        if VESAInfo.Version >= $0200 then
1769
 
          Begin
1770
 
            { Alllocate real mode buffer }
1771
 
{$ifndef fpc}
1772
 
            Ptr:=GlobalDosAlloc(sizeof(palrec));
1773
 
            { get the selector value }
1774
 
            PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
1775
 
            if not assigned(PalPtr) then
1776
 
               RunError(203);
1777
 
{$else fpc}
1778
 
            Ptr:=Global_Dos_Alloc(sizeof(palrec));
1779
 
{$endif fpc}
1780
 
            { get the segment value }
1781
 
            RealSeg := word(Ptr shr 16);
1782
 
            { setup interrupt registers }
1783
 
            FillChar(regs, sizeof(regs), #0);
1784
 
 
1785
 
            regs.eax := $4F09;
1786
 
            regs.ebx := $01;       { get palette data      }
1787
 
            regs.ecx := $01;
1788
 
            regs.edx := ColorNum;
1789
 
            regs.es  := RealSeg;
1790
 
            regs.edi := 0;         { offset is always zero }
1791
 
            RealIntr($10, regs);
1792
 
 
1793
 
           { copy to protected mode buffer ... }
1794
 
{$ifndef fpc}
1795
 
           Move(PalPtr^, Pal, sizeof(pal));
1796
 
{$else fpc}
1797
 
           DosMemGet(RealSeg,0,Pal,sizeof(pal));
1798
 
{$endif fpc}
1799
 
           { free real mode memory  }
1800
 
{$ifndef fpc}
1801
 
           GlobalDosFree(word(Ptr and $ffff));
1802
 
{$else fpc}
1803
 
           If not Global_Dos_Free(word(Ptr and $ffff)) then
1804
 
             RunError(216);
1805
 
{$endif fpc}
1806
 
 
1807
 
            if word(regs.eax) <> $004F then
1808
 
              begin
1809
 
{$ifdef logging}
1810
 
                logln('getvesargbpalette failed while directcolor = false!');
1811
 
{$endif logging}
1812
 
                _GraphResult := grError;
1813
 
                exit;
1814
 
              end
1815
 
            else
1816
 
              begin
1817
 
                RedValue := Integer(pal.Red);
1818
 
                GreenValue := Integer(pal.Green);
1819
 
                BlueValue := Integer(pal.Blue);
1820
 
              end;
1821
 
          end
1822
 
        else
1823
 
            GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1824
 
   end;
1825
 
{$ELSE}
1826
 
 
1827
 
   Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
1828
 
      BlueValue : Integer); far;
1829
 
    var
1830
 
     FunctionNr : byte;   { use blankbit or normal RAMDAC programming? }
1831
 
     pal: ^palrec;
1832
 
     Error : boolean;     { VBE call error                             }
1833
 
    begin
1834
 
      if DirectColor then
1835
 
        Begin
1836
 
          _GraphResult := grError;
1837
 
          exit;
1838
 
        end;
1839
 
        Error := FALSE;
1840
 
        new(pal);
1841
 
        if not assigned(pal) then RunError(203);
1842
 
        pal^.align := 0;
1843
 
        pal^.red := byte(RedValue);
1844
 
        pal^.green := byte(GreenValue);
1845
 
        pal^.blue := byte(BlueValue);
1846
 
        { use the set/get palette function }
1847
 
        if VESAInfo.Version >= $0200 then
1848
 
          Begin
1849
 
            { check if blanking bit must be set when programming }
1850
 
            { the RAMDAC.                                        }
1851
 
            if (VESAInfo.caps and attrSnowCheck) <> 0 then
1852
 
              FunctionNr := $80
1853
 
            else
1854
 
              FunctionNr := $00;
1855
 
            asm
1856
 
              mov  ax, 4F09h         { Set/Get Palette data    }
1857
 
              mov  bl, [FunctionNr]  { Set palette data        }
1858
 
              mov  cx, 01h           { update one palette reg. }
1859
 
              mov  dx, [ColorNum]    { register number to update }
1860
 
              les  di, [pal]         { get palette address     }
1861
 
              int  10h
1862
 
              cmp  ax, 004Fh         { check if success        }
1863
 
              jz   @noerror
1864
 
              mov  [Error], TRUE
1865
 
             @noerror:
1866
 
            end;
1867
 
            if not Error then
1868
 
                Dispose(pal)
1869
 
            else
1870
 
              begin
1871
 
                _GraphResult := grError;
1872
 
                exit;
1873
 
              end;
1874
 
          end
1875
 
        else
1876
 
          { assume it's fully VGA compatible palette-wise. }
1877
 
          Begin
1878
 
            SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1879
 
          end;
1880
 
    end;
1881
 
 
1882
 
 
1883
 
 
1884
 
 
1885
 
  Procedure GetVESARGBPalette(ColorNum: integer; Var RedValue, GreenValue,
1886
 
              BlueValue : integer); far;
1887
 
   var
1888
 
    Error: boolean;
1889
 
    pal: ^palrec;
1890
 
   begin
1891
 
      if DirectColor then
1892
 
        Begin
1893
 
          _GraphResult := grError;
1894
 
          exit;
1895
 
        end;
1896
 
      Error := FALSE;
1897
 
      new(pal);
1898
 
      if not assigned(pal) then RunError(203);
1899
 
      FillChar(pal^, sizeof(palrec), #0);
1900
 
      { use the set/get palette function }
1901
 
      if VESAInfo.Version >= $0200 then
1902
 
        Begin
1903
 
          asm
1904
 
            mov  ax, 4F09h         { Set/Get Palette data    }
1905
 
            mov  bl, 01h           { Set palette data        }
1906
 
            mov  cx, 01h           { update one palette reg. }
1907
 
            mov  dx, [ColorNum]    { register number to update }
1908
 
            les  di, [pal]         { get palette address     }
1909
 
            int  10h
1910
 
            cmp  ax, 004Fh         { check if success        }
1911
 
            jz   @noerror
1912
 
            mov  [Error], TRUE
1913
 
          @noerror:
1914
 
          end;
1915
 
          if not Error then
1916
 
            begin
1917
 
              RedValue := Integer(pal^.Red);
1918
 
              GreenValue := Integer(pal^.Green);
1919
 
              BlueValue := Integer(pal^.Blue);
1920
 
              Dispose(pal);
1921
 
            end
1922
 
          else
1923
 
            begin
1924
 
              _GraphResult := grError;
1925
 
              exit;
1926
 
            end;
1927
 
        end
1928
 
        else
1929
 
            GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
1930
 
 
1931
 
   end;
1932
 
{$ENDIF}
1933
 
 
1934
 
 
1935
 
(*
1936
 
type
1937
 
  heaperrorproc=function(size:longint):integer;
1938
 
 
1939
 
Const
1940
 
  HeapErrorIsHooked : boolean = false;
1941
 
  OldHeapError : HeapErrorProc = nil;
1942
 
  DsLimit : dword = 0;
1943
 
 
1944
 
  function NewHeapError(size : longint) : integer;
1945
 
    begin
1946
 
      set_segment_limit(get_ds,DsLimit);
1947
 
      NewHeapError:=OldHeapError(size);
1948
 
      DsLimit:=get_segment_limit(get_ds);
1949
 
      { The base of ds can be changed
1950
 
        we need to compute the address again PM }
1951
 
      LFBPointer:=pointer(FrameBufferLinearAddress-get_segment_base_address(get_ds));
1952
 
      if dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1 > DsLimit then
1953
 
        set_segment_limit(get_ds,dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1);
1954
 
    end;
1955
 
 
1956
 
  procedure HookHeapError;
1957
 
    begin
1958
 
      if HeapErrorIsHooked then
1959
 
        exit;
1960
 
      DsLimit:=get_segment_limit(get_ds);
1961
 
      OldHeapError:=HeapErrorProc(HeapError);
1962
 
      HeapError:=@NewHeapError;
1963
 
      HeapErrorIsHooked:=true;
1964
 
    end;
1965
 
 
1966
 
  procedure UnHookHeapError;
1967
 
    begin
1968
 
      if not HeapErrorIsHooked then
1969
 
        exit;
1970
 
      LFBPointer:=nil;
1971
 
      set_segment_limit(get_ds,DsLimit);
1972
 
      HeapError:=OldHeapError;
1973
 
      HeapErrorIsHooked:=false;
1974
 
    end;
1975
 
*)
1976
 
 
1977
 
  function SetupLinear(var ModeInfo: TVESAModeInfo;mode : word) : boolean;
1978
 
   begin
1979
 
     SetUpLinear:=false;
1980
 
{$ifdef FPC}
1981
 
     case mode of
1982
 
       m320x200x32k,
1983
 
       m320x200x64k,
1984
 
       m640x480x32k,
1985
 
       m640x480x64k,
1986
 
       m800x600x32k,
1987
 
       m800x600x64k,
1988
 
       m1024x768x32k,
1989
 
       m1024x768x64k,
1990
 
       m1280x1024x32k,
1991
 
       m1280x1024x64k :
1992
 
         begin
1993
 
           DirectPutPixel:=@DirectPutPixVESA32kor64kLinear;
1994
 
           PutPixel:=@PutPixVESA32kor64kLinear;
1995
 
           GetPixel:=@GetPixVESA32kor64kLinear;
1996
 
           { linear mode for lines not yet implemented PM }
1997
 
           HLine:=@HLineDefault;
1998
 
           VLine:=@VLineDefault;
1999
 
           GetScanLine := @GetScanLineDefault;
2000
 
           PatternLine := @PatternLineDefault;
2001
 
         end;
2002
 
       m640x400x256,
2003
 
       m640x480x256,
2004
 
       m800x600x256,
2005
 
       m1024x768x256,
2006
 
       m1280x1024x256:
2007
 
         begin
2008
 
           DirectPutPixel:=@DirectPutPixVESA256Linear;
2009
 
           PutPixel:=@PutPixVESA256Linear;
2010
 
           GetPixel:=@GetPixVESA256Linear;
2011
 
           { linear mode for lines not yet implemented PM }
2012
 
           HLine:=@HLineDefault;
2013
 
           VLine:=@VLineDefault;
2014
 
           GetScanLine := @GetScanLineDefault;
2015
 
           PatternLine := @PatternLineDefault;
2016
 
         end;
2017
 
     else
2018
 
       exit;
2019
 
     end;
2020
 
     FrameBufferLinearAddress:=Get_linear_addr(VESAModeInfo.PhysAddress and $FFFF0000,
2021
 
       VESAInfo.TotalMem shl 16);
2022
 
{$ifdef logging}
2023
 
     logln('framebuffer linear address: '+hexstr(FrameBufferLinearAddress div (1024*1024),8));
2024
 
     logln('total mem shl 16: '+strf(vesainfo.totalmem shl 16));
2025
 
{$endif logging}
2026
 
     if int31error<>0 then
2027
 
       begin
2028
 
{$ifdef logging}
2029
 
         logln('Unable to get linear address for '+hexstr(VESAModeInfo.PhysAddress,8));
2030
 
{$endif logging}
2031
 
         writeln(stderr,'Unable to get linear address for ',hexstr(VESAModeInfo.PhysAddress,8));
2032
 
         exit;
2033
 
       end;
2034
 
     if UseNoSelector then
2035
 
       begin
2036
 
{         HookHeapError; }
2037
 
         LFBPointer:=pointer(FrameBufferLinearAddress-get_segment_base_address(get_ds));
2038
 
         if dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1 > dword(get_segment_limit(get_ds)) then
2039
 
           set_segment_limit(get_ds,dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1);
2040
 
       end
2041
 
     else
2042
 
       begin
2043
 
         WinWriteSeg:=allocate_ldt_descriptors(1);
2044
 
{$ifdef logging}
2045
 
         logln('writeseg1: '+hexstr(winwriteseg,8));
2046
 
{$endif logging}
2047
 
         set_segment_base_address(WinWriteSeg,FrameBufferLinearAddress);
2048
 
         set_segment_limit(WinWriteSeg,(VESAInfo.TotalMem shl 16)-1);
2049
 
         lock_linear_region(FrameBufferLinearAddress,(VESAInfo.TotalMem shl 16));
2050
 
         if int31error<>0 then
2051
 
           begin
2052
 
{$ifdef logging}
2053
 
             logln('Error in linear memory selectors creation');
2054
 
{$endif logging}
2055
 
             writeln(stderr,'Error in linear memory selectors creation');
2056
 
             exit;
2057
 
           end;
2058
 
       end;
2059
 
     LinearPageOfs := 0;
2060
 
     InLinear:=true;
2061
 
     SetUpLinear:=true;
2062
 
     { WinSize:=(VGAInfo.TotalMem shl 16);
2063
 
     WinLoMask:=(VGAInfo.TotalMem shl 16)-1;
2064
 
     WinShift:=15;
2065
 
     Temp:=VGAInfo.TotalMem;
2066
 
     while Temp>0 do
2067
 
       begin
2068
 
         inc(WinShift);
2069
 
         Temp:=Temp shr 1;
2070
 
       end; }
2071
 
{$endif FPC}
2072
 
   end;
2073
 
 
2074
 
  procedure SetupWindows(var ModeInfo: TVESAModeInfo);
2075
 
   begin
2076
 
     InLinear:=false;
2077
 
     { now we check the windowing scheme ...}
2078
 
     if (ModeInfo.WinAAttr and WinSupported) <> 0 then
2079
 
       { is this window supported ... }
2080
 
       begin
2081
 
         { now check if the window is R/W }
2082
 
         if (ModeInfo.WinAAttr and WinReadable) <> 0 then
2083
 
         begin
2084
 
           ReadWindow := 0;
2085
 
           WinReadSeg := ModeInfo.WinASeg;
2086
 
         end;
2087
 
         if (ModeInfo.WinAAttr and WinWritable) <> 0 then
2088
 
         begin
2089
 
           WriteWindow := 0;
2090
 
           WinWriteSeg := ModeInfo.WinASeg;
2091
 
         end;
2092
 
       end;
2093
 
     if (ModeInfo.WinBAttr and WinSupported) <> 0 then
2094
 
       { is this window supported ... }
2095
 
       begin
2096
 
 
2097
 
         { OPTIMIZATION ... }
2098
 
         { if window A supports both read/write, then we try to optimize }
2099
 
         { everything, by using a different window for Read and/or write.}
2100
 
         if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
2101
 
           begin
2102
 
              { check if winB supports read }
2103
 
              if (ModeInfo.WinBAttr and winReadable) <> 0 then
2104
 
                begin
2105
 
                  WinReadSeg := ModeInfo.WinBSeg;
2106
 
                  ReadWindow := 1;
2107
 
                end
2108
 
              else
2109
 
              { check if WinB supports write }
2110
 
              if (ModeInfo.WinBAttr and WinWritable) <> 0 then
2111
 
                begin
2112
 
                  WinWriteSeg := ModeInfo.WinBSeg;
2113
 
                  WriteWindow := 1;
2114
 
                end;
2115
 
           end
2116
 
         else
2117
 
         { Window A only supported Read OR Write, no we have to make }
2118
 
         { sure that window B supports the other mode.               }
2119
 
         if (WinReadSeg = 0) and (WinWriteSeg<>0) then
2120
 
           begin
2121
 
              if (ModeInfo.WinBAttr and WinReadable <> 0) then
2122
 
                begin
2123
 
                  ReadWindow := 1;
2124
 
                  WinReadSeg := ModeInfo.WinBSeg;
2125
 
                end
2126
 
              else
2127
 
                { impossible, this VESA mode is WRITE only! }
2128
 
                begin
2129
 
                  WriteLn('Invalid VESA Window attribute.');
2130
 
                  Halt(255);
2131
 
                end;
2132
 
           end
2133
 
         else
2134
 
         if (winWriteSeg = 0) and (WinReadSeg<>0) then
2135
 
           begin
2136
 
             if (ModeInfo.WinBAttr and WinWritable) <> 0 then
2137
 
               begin
2138
 
                 WriteWindow := 1;
2139
 
                 WinWriteSeg := ModeInfo.WinBSeg;
2140
 
               end
2141
 
             else
2142
 
               { impossible, this VESA mode is READ only! }
2143
 
               begin
2144
 
                  WriteLn('Invalid VESA Window attribute.');
2145
 
                  Halt(255);
2146
 
               end;
2147
 
           end
2148
 
         else
2149
 
         if (winReadSeg = 0) and (winWriteSeg = 0) then
2150
 
         { no read/write in this mode! }
2151
 
           begin
2152
 
                  WriteLn('Invalid VESA Window attribute.');
2153
 
                  Halt(255);
2154
 
           end;
2155
 
         YOffset := 0;
2156
 
       end;
2157
 
 
2158
 
     { if both windows are not supported, then we can assume }
2159
 
     { that there is ONE single NON relocatable window.      }
2160
 
     if (WinWriteSeg = 0) and (WinReadSeg = 0) then
2161
 
       begin
2162
 
         WinWriteSeg := ModeInfo.WinASeg;
2163
 
         WinReadSeg := ModeInfo.WinASeg;
2164
 
       end;
2165
 
 
2166
 
    { 16-bit Protected mode checking code...  }
2167
 
    { change segment values to protected mode }
2168
 
    { selectors.                              }
2169
 
    if WinReadSeg = $A000 then
2170
 
      WinReadSeg := SegA000
2171
 
    else
2172
 
    if WinReadSeg = $B000 then
2173
 
      WinReadSeg := SegB000
2174
 
    else
2175
 
    if WinReadSeg = $B800 then
2176
 
      WinReadSeg := SegB800
2177
 
    else
2178
 
      begin
2179
 
        WriteLn('Invalid segment address.');
2180
 
        Halt(255);
2181
 
      end;
2182
 
    if WinWriteSeg = $A000 then
2183
 
      WinWriteSeg := SegA000
2184
 
    else
2185
 
    if WinWriteSeg = $B000 then
2186
 
      WinWriteSeg := SegB000
2187
 
    else
2188
 
    if WinWriteSeg = $B800 then
2189
 
      WinWriteSeg := SegB800
2190
 
    else
2191
 
      begin
2192
 
        WriteLn('Invalid segment address.');
2193
 
        Halt(255);
2194
 
      end;
2195
 
 
2196
 
   end;
2197
 
 
2198
 
 
2199
 
 
2200
 
  function setVESAMode(mode:word):boolean;
2201
 
    var i:word;
2202
 
        res: boolean;
2203
 
  begin
2204
 
   { Init mode information, for compatibility with VBE < 1.1 }
2205
 
   FillChar(VESAModeInfo, sizeof(TVESAModeInfo), #0);
2206
 
   { get the video mode information }
2207
 
   if getVESAModeInfo(VESAmodeinfo, mode) then
2208
 
   begin
2209
 
     { checks if the hardware supports the video mode. }
2210
 
     if (VESAModeInfo.attr and modeAvail) = 0 then
2211
 
       begin
2212
 
         SetVESAmode := FALSE;
2213
 
{$ifdef logging}
2214
 
         logln('  vesa mode '+strf(mode)+' not supported!!!');
2215
 
{$endif logging}
2216
 
         _GraphResult := grError;
2217
 
         exit;
2218
 
       end;
2219
 
 
2220
 
     SetVESAMode := TRUE;
2221
 
     BankShift := 0;
2222
 
     while (64 shr BankShift) <> VESAModeInfo.WinGranularity do
2223
 
        Inc(BankShift);
2224
 
     CurrentWriteBank := -1;
2225
 
     CurrentReadBank := -1;
2226
 
     BytesPerLine := VESAModeInfo.BytesPerScanLine;
2227
 
 
2228
 
     { These are the window adresses ... }
2229
 
     WinWriteSeg := 0;  { This is the segment to use for writes }
2230
 
     WinReadSeg := 0;   { This is the segment to use for reads  }
2231
 
     ReadWindow := 0;
2232
 
     WriteWindow := 0;
2233
 
 
2234
 
     { VBE 2.0 and higher supports >= non VGA linear buffer types...}
2235
 
     { this is backward compatible.                                 }
2236
 
     if (((VESAModeInfo.Attr and ModeNoWindowed) <> 0) or UseLFB) and
2237
 
          ((VESAModeInfo.Attr and ModeLinearBuffer) <> 0) then
2238
 
        begin
2239
 
          if not SetupLinear(VESAModeInfo,mode) then
2240
 
            SetUpWindows(VESAModeInfo);
2241
 
        end
2242
 
     else
2243
 
     { if linear and windowed is supported, then use windowed }
2244
 
     { method.                                                }
2245
 
        SetUpWindows(VESAModeInfo);
2246
 
 
2247
 
{$ifdef logging}
2248
 
  LogLn('Entering vesa mode '+strf(mode));
2249
 
  LogLn('Read segment: $'+hexstr(winreadseg,4));
2250
 
  LogLn('Write segment: $'+hexstr(winwriteseg,4));
2251
 
  LogLn('Window granularity: '+strf(VESAModeInfo.WinGranularity)+'kb');
2252
 
  LogLn('Window size: '+strf(VESAModeInfo.winSize)+'kb');
2253
 
  LogLn('Bytes per line: '+strf(bytesperline));
2254
 
{$endif logging}
2255
 
   { Select the correct mode number if we're going to use linear access! }
2256
 
   if InLinear then
2257
 
     inc(mode,$4000);
2258
 
 
2259
 
   asm
2260
 
    mov ax,4F02h
2261
 
    mov bx,mode
2262
 
{$ifdef fpc}
2263
 
    push ebp
2264
 
{$endif fpc}
2265
 
    int 10h
2266
 
{$ifdef fpc}
2267
 
    pop ebp
2268
 
{$endif fpc}
2269
 
    sub ax,004Fh
2270
 
    cmp ax,1
2271
 
    sbb al,al
2272
 
    mov res,al
2273
 
   end;
2274
 
   if not res then
2275
 
     _GraphResult := GrNotDetected
2276
 
   else _GraphResult := grOk;
2277
 
  end;
2278
 
 end;
2279
 
 
2280
 
(*
2281
 
 function getVESAMode:word;assembler;
2282
 
   asm  {return -1 if error}
2283
 
    mov ax,4F03h
2284
 
{$ifdef fpc}
2285
 
    push ebp
2286
 
{$endif fpc}
2287
 
    int 10h
2288
 
{$ifdef fpc}
2289
 
    pop ebp
2290
 
{$endif fpc}
2291
 
    cmp ax,004Fh
2292
 
    je @@OK
2293
 
    mov ax,-1
2294
 
    jmp @@X
2295
 
  @@OK:
2296
 
    mov ax,bx
2297
 
  @@X:
2298
 
   end;
2299
 
*)
2300
 
 
2301
 
 
2302
 
 
2303
 
 {************************************************************************}
2304
 
 {*                     VESA Modes inits                                 *}
2305
 
 {************************************************************************}
2306
 
 
2307
 
{$IFDEF DPMI}
2308
 
 
2309
 
  {******************************************************** }
2310
 
  { Function GetMaxScanLines()                              }
2311
 
  {-------------------------------------------------------- }
2312
 
  { This routine returns the maximum number of scan lines   }
2313
 
  { possible for this mode. This is done using the Get      }
2314
 
  { Scan Line length VBE function.                          }
2315
 
  {******************************************************** }
2316
 
  function GetMaxScanLines: word;
2317
 
   var
2318
 
    regs : TDPMIRegisters;
2319
 
   begin
2320
 
     FillChar(regs, sizeof(regs), #0);
2321
 
     { play it safe, call the real mode int, the 32-bit entry point }
2322
 
     { may not be defined as stated in VBE v3.0                     }
2323
 
     regs.eax := $4f06; {_ setup function      }
2324
 
     regs.ebx := $0001; { get scan line length }
2325
 
     RealIntr($10, regs);
2326
 
     GetMaxScanLines := (regs.edx and $0000ffff);
2327
 
   end;
2328
 
 
2329
 
{$ELSE}
2330
 
 
2331
 
  function GetMaxScanLines: word; assembler;
2332
 
     asm
2333
 
      mov ax, 4f06h
2334
 
      mov bx, 0001h
2335
 
      int 10h
2336
 
      mov ax, dx
2337
 
   end;
2338
 
 
2339
 
{$ENDIF}
2340
 
 
2341
 
 procedure Init1280x1024x64k; {$ifndef fpc}far;{$endif fpc}
2342
 
  begin
2343
 
    SetVesaMode(m1280x1024x64k);
2344
 
    { Get maximum number of scanlines for page flipping }
2345
 
    ScanLines := GetMaxScanLines;
2346
 
  end;
2347
 
 
2348
 
 procedure Init1280x1024x32k; {$ifndef fpc}far;{$endif fpc}
2349
 
  begin
2350
 
    SetVESAMode(m1280x1024x32k);
2351
 
    { Get maximum number of scanlines for page flipping }
2352
 
    ScanLines := GetMaxScanLines;
2353
 
  end;
2354
 
 
2355
 
 procedure Init1280x1024x256; {$ifndef fpc}far;{$endif fpc}
2356
 
  begin
2357
 
    SetVESAMode(m1280x1024x256);
2358
 
    { Get maximum number of scanlines for page flipping }
2359
 
    ScanLines := GetMaxScanLines;
2360
 
  end;
2361
 
 
2362
 
 
2363
 
 procedure Init1280x1024x16; {$ifndef fpc}far;{$endif fpc}
2364
 
  begin
2365
 
    SetVESAMode(m1280x1024x16);
2366
 
    { Get maximum number of scanlines for page flipping }
2367
 
    ScanLines := GetMaxScanLines;
2368
 
  end;
2369
 
 
2370
 
 procedure Init1024x768x64k; {$ifndef fpc}far;{$endif fpc}
2371
 
  begin
2372
 
    SetVESAMode(m1024x768x64k);
2373
 
    { Get maximum number of scanlines for page flipping }
2374
 
    ScanLines := GetMaxScanLines;
2375
 
  end;
2376
 
 
2377
 
 procedure Init640x480x32k; {$ifndef fpc}far;{$endif fpc}
2378
 
  begin
2379
 
    SetVESAMode(m640x480x32k);
2380
 
    { Get maximum number of scanlines for page flipping }
2381
 
    ScanLines := GetMaxScanLines;
2382
 
  end;
2383
 
 
2384
 
 procedure Init1024x768x256; {$ifndef fpc}far;{$endif fpc}
2385
 
  begin
2386
 
    SetVESAMode(m1024x768x256);
2387
 
    { Get maximum number of scanlines for page flipping }
2388
 
    ScanLines := GetMaxScanLines;
2389
 
  end;
2390
 
 
2391
 
 procedure Init1024x768x16; {$ifndef fpc}far;{$endif fpc}
2392
 
  begin
2393
 
    SetVESAMode(m1024x768x16);
2394
 
    { Get maximum number of scanlines for page flipping }
2395
 
    ScanLines := GetMaxScanLines;
2396
 
  end;
2397
 
 
2398
 
 procedure Init800x600x64k; {$ifndef fpc}far;{$endif fpc}
2399
 
  begin
2400
 
    SetVESAMode(m800x600x64k);
2401
 
    { Get maximum number of scanlines for page flipping }
2402
 
    ScanLines := GetMaxScanLines;
2403
 
  end;
2404
 
 
2405
 
 procedure Init800x600x32k; {$ifndef fpc}far;{$endif fpc}
2406
 
  begin
2407
 
    SetVESAMode(m800x600x32k);
2408
 
    { Get maximum number of scanlines for page flipping }
2409
 
    ScanLines := GetMaxScanLines;
2410
 
  end;
2411
 
 
2412
 
 procedure Init800x600x256; {$ifndef fpc}far;{$endif fpc}
2413
 
  begin
2414
 
    SetVESAMode(m800x600x256);
2415
 
    { Get maximum number of scanlines for page flipping }
2416
 
    ScanLines := GetMaxScanLines;
2417
 
  end;
2418
 
 
2419
 
 procedure Init800x600x16; {$ifndef fpc}far;{$endif fpc}
2420
 
  begin
2421
 
    SetVesaMode(m800x600x16);
2422
 
    { Get maximum number of scanlines for page flipping }
2423
 
    ScanLines := GetMaxScanLines;
2424
 
  end;
2425
 
 
2426
 
 procedure Init640x480x64k; {$ifndef fpc}far;{$endif fpc}
2427
 
  begin
2428
 
    SetVESAMode(m640x480x64k);
2429
 
    { Get maximum number of scanlines for page flipping }
2430
 
    ScanLines := GetMaxScanLines;
2431
 
  end;
2432
 
 
2433
 
 
2434
 
 procedure Init640x480x256; {$ifndef fpc}far;{$endif fpc}
2435
 
  begin
2436
 
    SetVESAMode(m640x480x256);
2437
 
    { Get maximum number of scanlines for page flipping }
2438
 
    ScanLines := GetMaxScanLines;
2439
 
  end;
2440
 
 
2441
 
 procedure Init640x400x256; {$ifndef fpc}far;{$endif fpc}
2442
 
  begin
2443
 
    SetVESAMode(m640x400x256);
2444
 
    { Get maximum number of scanlines for page flipping }
2445
 
    ScanLines := GetMaxScanLines;
2446
 
  end;
2447
 
 
2448
 
 procedure Init320x200x64k; {$ifndef fpc}far;{$endif fpc}
2449
 
  begin
2450
 
    SetVESAMode(m320x200x64k);
2451
 
    { Get maximum number of scanlines for page flipping }
2452
 
    ScanLines := GetMaxScanLines;
2453
 
  end;
2454
 
 
2455
 
 procedure Init320x200x32k; {$ifndef fpc}far;{$endif fpc}
2456
 
  begin
2457
 
    SetVESAMode(m320x200x32k);
2458
 
    { Get maximum number of scanlines for page flipping }
2459
 
    ScanLines := GetMaxScanLines;
2460
 
  end;
2461
 
 
2462
 
 
2463
 
{$IFDEF DPMI}
2464
 
 
2465
 
 Procedure SaveStateVESA; {$ifndef fpc}far;{$endif fpc}
2466
 
 var
2467
 
  PtrLong: longint;
2468
 
  regs: TDPMIRegisters;
2469
 
  begin
2470
 
    SaveSupported := FALSE;
2471
 
    SavePtr := nil;
2472
 
{$ifdef logging}
2473
 
        LogLn('Get the video mode...');
2474
 
{$endif logging}
2475
 
    { Get the video mode }
2476
 
    asm
2477
 
      mov  ah,0fh
2478
 
{$ifdef fpc}
2479
 
      push ebp
2480
 
{$endif fpc}
2481
 
      int  10h
2482
 
{$ifdef fpc}
2483
 
      pop ebp
2484
 
{$endif fpc}
2485
 
      mov  [VideoMode], al
2486
 
    end;
2487
 
    { saving/restoring video state screws up Windows (JM) }
2488
 
    if inWindows then
2489
 
      exit;
2490
 
{$ifdef logging}
2491
 
        LogLn('Prepare to save VESA video state');
2492
 
{$endif logging}
2493
 
    { Prepare to save video state...}
2494
 
    asm
2495
 
      mov  ax, 4F04h       { get buffer size to save state }
2496
 
      mov  dx, 00h
2497
 
      mov  cx, 00001111b   { Save DAC / Data areas / Hardware states }
2498
 
{$ifdef fpc}
2499
 
      push ebp
2500
 
{$endif fpc}
2501
 
      int  10h
2502
 
{$ifdef fpc}
2503
 
      pop ebp
2504
 
{$endif fpc}
2505
 
      mov  [StateSize], bx
2506
 
      cmp  al,04fh
2507
 
      jnz  @notok
2508
 
      mov  [SaveSupported],TRUE
2509
 
     @notok:
2510
 
    end;
2511
 
    regs.eax := $4f04;
2512
 
    regs.edx := $0000;
2513
 
    regs.ecx := $000F;
2514
 
    RealIntr($10, regs);
2515
 
    StateSize := word(regs.ebx);
2516
 
    if byte(regs.eax) = $4f then
2517
 
      SaveSupported := TRUE;
2518
 
    if SaveSupported then
2519
 
      begin
2520
 
{$ifdef logging}
2521
 
        LogLn('allocating VESA save buffer of '+strf(64*StateSize));
2522
 
{$endif logging}
2523
 
{$ifndef fpc}
2524
 
        PtrLong:=GlobalDosAlloc(64*StateSize);  { values returned in 64-byte blocks }
2525
 
{$else fpc}
2526
 
        PtrLong:=Global_Dos_Alloc(64*StateSize);  { values returned in 64-byte blocks }
2527
 
{$endif fpc}
2528
 
        if PtrLong = 0 then
2529
 
           RunError(203);
2530
 
        SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
2531
 
{$ifndef fpc}
2532
 
        { In FPC mode, we can't do anything with this (no far pointers)  }
2533
 
        { However, we still need to keep it to be able to free the       }
2534
 
        { memory afterwards. Since this data is not accessed in PM code, }
2535
 
        { there's no need to save it in a seperate buffer (JM)           }
2536
 
        if not assigned(SavePtr) then
2537
 
           RunError(203);
2538
 
{$endif fpc}
2539
 
        RealStateSeg := word(PtrLong shr 16);
2540
 
 
2541
 
        FillChar(regs, sizeof(regs), #0);
2542
 
        { call the real mode interrupt ... }
2543
 
        regs.eax := $4F04;      { save the state buffer                   }
2544
 
        regs.ecx := $0F;        { Save DAC / Data areas / Hardware states }
2545
 
        regs.edx := $01;        { save state                              }
2546
 
        regs.es := RealStateSeg;
2547
 
        regs.ebx := 0;
2548
 
        RealIntr($10,regs);
2549
 
        FillChar(regs, sizeof(regs), #0);
2550
 
        { restore state, according to Ralph Brown Interrupt list }
2551
 
        { some BIOS corrupt the hardware after a save...         }
2552
 
        regs.eax := $4F04;      { restore the state buffer                }
2553
 
        regs.ecx := $0F;        { rest DAC / Data areas / Hardware states }
2554
 
        regs.edx := $02;
2555
 
        regs.es := RealStateSeg;
2556
 
        regs.ebx := 0;
2557
 
        RealIntr($10,regs);
2558
 
      end;
2559
 
  end;
2560
 
 
2561
 
 procedure RestoreStateVESA; {$ifndef fpc}far;{$endif fpc}
2562
 
  var
2563
 
   regs:TDPMIRegisters;
2564
 
  begin
2565
 
     { go back to the old video mode...}
2566
 
     asm
2567
 
      mov  ah,00
2568
 
      mov  al,[VideoMode]
2569
 
{$ifdef fpc}
2570
 
      push ebp
2571
 
{$endif fpc}
2572
 
      int  10h
2573
 
{$ifdef fpc}
2574
 
      pop ebp
2575
 
{$endif fpc}
2576
 
     end;
2577
 
     { then restore all state information }
2578
 
{$ifndef fpc}
2579
 
     if assigned(SavePtr) and (SaveSupported=TRUE) then
2580
 
{$else fpc}
2581
 
     { No far pointer support, so it's possible that that assigned(SavePtr) }
2582
 
     { would return false under FPC. Just check if it's different from nil. }
2583
 
     if (SavePtr <> nil) and (SaveSupported=TRUE) then
2584
 
{$endif fpc}
2585
 
       begin
2586
 
        FillChar(regs, sizeof(regs), #0);
2587
 
        { restore state, according to Ralph Brown Interrupt list }
2588
 
        { some BIOS corrupt the hardware after a save...         }
2589
 
         regs.eax := $4F04;      { restore the state buffer                }
2590
 
         regs.ecx := $0F;        { rest DAC / Data areas / Hardware states }
2591
 
         regs.edx := $02;        { restore state                           }
2592
 
         regs.es := RealStateSeg;
2593
 
         regs.ebx := 0;
2594
 
         RealIntr($10,regs);
2595
 
{$ifndef fpc}
2596
 
         if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
2597
 
{$else fpc}
2598
 
         if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
2599
 
{$endif fpc}
2600
 
          RunError(216);
2601
 
         SavePtr := nil;
2602
 
       end;
2603
 
  end;
2604
 
 
2605
 
{$ELSE}
2606
 
 
2607
 
      {**************************************************************}
2608
 
      {*                     Real mode routines                     *}
2609
 
      {**************************************************************}
2610
 
 
2611
 
 Procedure SaveStateVESA; far;
2612
 
  begin
2613
 
    SavePtr := nil;
2614
 
    SaveSupported := FALSE;
2615
 
    { Get the video mode }
2616
 
    asm
2617
 
      mov  ah,0fh
2618
 
      int  10h
2619
 
      mov  [VideoMode], al
2620
 
    end;
2621
 
    { Prepare to save video state...}
2622
 
    asm
2623
 
      mov  ax, 4f04h       { get buffer size to save state }
2624
 
      mov  cx, 00001111b   { Save DAC / Data areas / Hardware states }
2625
 
      mov  dx, 00h
2626
 
      int  10h
2627
 
      mov  [StateSize], bx
2628
 
      cmp  al,04fh
2629
 
      jnz  @notok
2630
 
      mov  [SaveSupported],TRUE
2631
 
     @notok:
2632
 
    end;
2633
 
    if SaveSupported then
2634
 
      Begin
2635
 
        GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
2636
 
        if not assigned(SavePtr) then
2637
 
           RunError(203);
2638
 
        asm
2639
 
         mov  ax, 4F04h       { save the state buffer                   }
2640
 
         mov  cx, 00001111b   { Save DAC / Data areas / Hardware states }
2641
 
         mov  dx, 01h
2642
 
         mov  es, WORD PTR [SavePtr+2]
2643
 
         mov  bx, WORD PTR [SavePtr]
2644
 
         int  10h
2645
 
        end;
2646
 
        { restore state, according to Ralph Brown Interrupt list }
2647
 
        { some BIOS corrupt the hardware after a save...         }
2648
 
        asm
2649
 
         mov  ax, 4F04h       { save the state buffer                   }
2650
 
         mov  cx, 00001111b   { Save DAC / Data areas / Hardware states }
2651
 
         mov  dx, 02h
2652
 
         mov  es, WORD PTR [SavePtr+2]
2653
 
         mov  bx, WORD PTR [SavePtr]
2654
 
         int  10h
2655
 
        end;
2656
 
      end;
2657
 
  end;
2658
 
 
2659
 
 procedure RestoreStateVESA; far;
2660
 
  begin
2661
 
     { go back to the old video mode...}
2662
 
     asm
2663
 
      mov  ah,00
2664
 
      mov  al,[VideoMode]
2665
 
      int  10h
2666
 
     end;
2667
 
 
2668
 
     { then restore all state information }
2669
 
     if assigned(SavePtr) and (SaveSupported=TRUE) then
2670
 
       begin
2671
 
         { restore state, according to Ralph Brown Interrupt list }
2672
 
         asm
2673
 
           mov  ax, 4F04h       { save the state buffer                   }
2674
 
           mov  cx, 00001111b   { Save DAC / Data areas / Hardware states }
2675
 
           mov  dx, 02h         { restore state                           }
2676
 
           mov  es, WORD PTR [SavePtr+2]
2677
 
           mov  bx, WORD PTR [SavePtr]
2678
 
           int  10h
2679
 
         end;
2680
 
         FreeMem(SavePtr, 64*StateSize);
2681
 
         SavePtr := nil;
2682
 
       end;
2683
 
  end;
2684
 
{$ENDIF DPMI}
2685
 
 
2686
 
 {************************************************************************}
2687
 
 {*                     VESA Page flipping routines                      *}
2688
 
 {************************************************************************}
2689
 
 { Note: These routines, according  to the VBE3 specification, will NOT   }
2690
 
 { work with the 24 bpp modes, because of the alignment.                  }
2691
 
 {************************************************************************}
2692
 
 
2693
 
  {******************************************************** }
2694
 
  { Procedure SetVisualVESA()                               }
2695
 
  {-------------------------------------------------------- }
2696
 
  { This routine changes the page which will be displayed   }
2697
 
  { on the screen, since the method has changed somewhat    }
2698
 
  { between VBE versions , we will use the old method where }
2699
 
  { the new pixel offset is used to display different pages }
2700
 
  {******************************************************** }
2701
 
 procedure SetVisualVESA(page: word); {$ifndef fpc}far;{$endif fpc}
2702
 
  var
2703
 
   newStartVisible : word;
2704
 
  begin
2705
 
    if page > HardwarePages then
2706
 
      begin
2707
 
        _graphresult := grError;
2708
 
        exit;
2709
 
      end;
2710
 
    newStartVisible := (MaxY+1)*page;
2711
 
    if newStartVisible > ScanLines then
2712
 
      begin
2713
 
        _graphresult := grError;
2714
 
        exit;
2715
 
      end;
2716
 
    asm
2717
 
      mov ax, 4f07h
2718
 
      mov bx, 0000h   { set display start }
2719
 
      mov cx, 0000h   { pixel zero !      }
2720
 
      mov dx, [NewStartVisible]  { new scanline }
2721
 
{$ifdef fpc}
2722
 
      push    ebp
2723
 
{$endif}
2724
 
      int     10h
2725
 
{$ifdef fpc}
2726
 
      pop     ebp
2727
 
{$endif}
2728
 
    end;
2729
 
  end;
2730
 
 
2731
 
 procedure SetActiveVESA(page: word); {$ifndef fpc}far;{$endif fpc}
2732
 
  begin
2733
 
    { video offset is in pixels under VESA VBE! }
2734
 
    { This value is reset after a mode set to page ZERO = YOffset = 0 ) }
2735
 
    if page > HardwarePages then
2736
 
      begin
2737
 
        _graphresult := grError;
2738
 
        exit;
2739
 
      end;
2740
 
    YOffset := (MaxY+1)*page;
2741
 
    LinearPageOfs := YOffset*(MaxX+1);
2742
 
  end;
2743
 
 
2744
 
{
2745
 
  $Log: vesa.inc,v $
2746
 
  Revision 1.12  2005/02/14 17:13:22  peter
2747
 
    * truncate log
2748
 
 
2749
 
  Revision 1.11  2005/02/02 11:57:19  jonas
2750
 
    * fix from Tomas for calling conventions
2751
 
 
2752
 
}