[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]

{$F+,O+}
unit Screen_d;
INTERFACE

uses DOS, GRAPH;

type    RGBrec = record
                   redval, greenval, blueval: byte;
                 end;

var     SCRfilename: pathstr;
        file_error: boolean;
        pal: palettetype;
        RGBpal: array[0..15] of RGBrec;
        page_addr: word;
        bytes_per_line: word;
        buff0, buff1: pointer;

        { CGA display memory banks: }
        screenbuff0: array[0..7999] of byte absolute $b800:$0000;
        screenbuff1: array[0..7999] of byte absolute $b800:$2000;

const   page0 = $A000;           { EGA/VGA display segment }

procedure READSCR(pfilename: pathstr);

{========================================================================}

IMPLEMENTATION

var     scratch, abuff0, abuff1: pointer;
        is_VGA: boolean;
        repeatcount: byte;
        datalength: word;
        columncount, plane, video_index: word;
        regs: registers;

const   buffsize = 65521;   { Largest possible }

{ ====================== EGA/VGA 16-color files ========================= }

procedure DECODE_16; assembler;

asm
push    bp

{ ----------------- Assembler procedure for 16-color files -------------- }

{ The first section is initialization done on each run through the
  input buffer. }

@startproc:
mov     bp, plane           { plane in BP }
mov     es, page_addr       { video display segment }
mov     di, video_index     { index into video segment }
mov     ah, byte ptr bytes_per_line  { line length in AH }
mov     dx, columncount     { column counter }
mov     bx, datalength      { no. of bytes to read }
xor     cx, cx              { clean up CX for loop counter }
mov     cl, repeatcount     { count in CX }
push    ds                  { save DS }
lds     si, scratch         { input buffer pointer in DS:SI }
add     bx, si
cld                         { clear DF for stosb }
cmp     cl, 0               { was last byte a count? }
jne     @multi_data         { yes, so next is data }
jmp     @getbyte            { no, so find out what next is }

{ -------------- Procedure to write EGA/VGA image to video -------------- }

@writebyte:
stosb                       { AL into ES:DI, inc DI }
inc     dl                  { increment column }
cmp     dl, ah              { reached end of scanline? }
je      @doneline           { yes }
loop    @writebyte          { no, do another }
jmp     @getbyte            {   or get more data }
@doneline:
shl     bp, 1               { shift to next plane }
cmp     bp, 8               { done 4 planes? }
jle     @setindex           { no }
mov     bp, 1               { yes, reset plane to 1 but don't reset index }
jmp     @setplane
@setindex:
sub     di, dx              { reset to start of line }
@setplane:
push    ax                  { save AX }
cli                         { no interrupts }
mov     ax, bp              { plane is 1, 2, 4, or 8 }
mov     dx, 3C5h            { sequencer data register }
out     dx, al              { mask out 3 planes }
sti                         { enable interrupts }
pop     ax                  { restore AX }
xor     dx, dx              { reset column count }
loop    @writebyte          { do it again, or fetch more data }

@getbyte:                   { last byte was not a count }
cmp     si, bx              { end of input buffer? }
je      @exit               { yes, quit }
lodsb                       { get a byte from DS:SI into AL, increment SI }
cmp     al, 192             { test high bits }
jb      @one_data           { not set, it's data to be written once }
 { It's a count byte: }
xor     al, 192             { get count from 6 low bits }
mov     cl, al              { store repeat count }
cmp     si, bx              { end of input buffer? }
je      @exit               { yes, quit }
@multi_data:
lodsb                       { get data byte }
jmp     @writebyte          { write it CL times }
@one_data:
mov     cl, 1               { write byte once }
jmp     @writebyte

{ ---------------------- Finished with buffer --------------------------- }

@exit:
pop     ds                  { restore Turbo's data segment }
mov     plane, bp           { save status for next run thru buffer }
mov     repeatcount, cl
mov     columncount, dx
mov     video_index, di
pop     bp
end;  { asm }

{ ============= Main procedure for CGA and 16-color files =============== }

procedure READSCR(pfilename: pathstr);
type    ptrrec = record
                   segm, offs: word;
                 end;

var     entry, gun, SCRcode, mask, colorID: byte;
        palbuf: array[0..66] of byte;
        SCRfile: file;

begin   { READ_SCR_FILE }
        assign(SCRfile, pfilename);
        {$I-}
        reset(SCRfile, 1);
        {$I+}
        getmem(scratch, buffsize);                 { Allocate scratchpad }
        blockread(SCRfile, scratch^, 128);         { Get header into scratchpad }
        move(scratch^, palbuf, 67);
        bytes_per_line:= palbuf[66];
        begin
             video_index:= 0;
             port[$3C4]:= 2;           { Index to map mask register }
             plane:= 1;                { Initialize plane }
             port[$3C5]:= plane;       { Set sequencer to mask out other planes }

             for entry:= 0 to 15 do
             begin
             colorID:= 0;
             for gun:= 0 to 2 do
             begin
                  SCRcode:= palbuf[16 + entry * 3 + gun];   { Get primary color value }
                  begin
                  with RGBpal[entry] do                   { Interpret for VGA }
                       case gun of
                        0: redval:= SCRcode div 4;
                        1: greenval:= SCRcode div 4;
                        2: blueval:= SCRcode div 4;
                       end;
                  end;  { is_VGA }
                  end;  { gun }
                  pal.colors[entry]:= entry;
             end;  { entry }
             pal.size:= 16;
        end;   { not is_CGA }
        repeatcount:= 0;                        { Initialize assembler vars. }
        columncount:= 0;
        repeat
              blockread(SCRfile, scratch^, buffsize, datalength);
              decode_16;   { Call assembler routine }
        until eof(SCRfile);
        close(SCRfile);
        freemem(scratch,buffsize);              { Discard scratchpad }
end;  { READ_SCR_FILE }

Begin
     Page_addr := Page0;
END.


[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]