Board index » delphi » Graphic screen saving problem

Graphic screen saving problem

USES CRT,GRAPH;

TYPE PIC = ARRAY[1..480,1..80] OF BYTE;

VAR PICTURE : PIC ABSOLUTE $A000:$0;
PICFILE : FILE OF PIC;

BEGIN
GRON; {SET TO 640X480/16 MODE}
SETCOLOR(WHITE);
CIRCLE(320,200,100); {OR ANY DRAWING}
ASSIGN(PICFILE,'PICTURE.DAT');
REWRITE(PICFILE);
WRITE(PICFILE,PICTURE);
CLOSE(PICFILE);
END.

{This method saves the 640x480/16 graphic screen, at least
the pixels (not the colors).) But this method does not
work if "gron" sets the graphic into 640x480/256 color
mode. Why? Thanks. Joe}

 

Re:Graphic screen saving problem


Quote
Joseph Szadai wrote:
> {This method saves the 640x480/16 graphic screen, at least
> the pixels (not the colors).) But this method does not
> work if "gron" sets the graphic into 640x480/256 color
> mode. Why? Thanks. Joe}

Because a 640x480 graphics screen with 256 colors is 640x480 = 307200
bytes large. Data structures cannot be greater than 64 kb due to the
16-bit nature of the code produced by the compiler. Therefore, an
array[1..640, 1..480] of byte cannot be declared.

You won't find the whole 307200 bytes at memory location A000:0000. The
screen is divided into banks which are generally 64 kb large. You have
to do bank switching in order to write to or read from different parts
of the screen.
Depending on which bank you write to (0, 1, 2, ...), you in fact write
to a different of the screen. For example, bank 0 covers lines 1..100,
bank 1 convers 101..200 (just examples, I haven't verified this). The
location of the banks is always A000:0000. See interrupt 10h, function
4F05h.

Re:Graphic screen saving problem


In article <84l73s$rq...@freenet9.carleton.ca>,

Quote
Joseph Szadai <cw...@FreeNet.Carleton.CA> wrote:
>USES CRT,GRAPH;

>TYPE PIC = ARRAY[1..480,1..80] OF BYTE;

>VAR PICTURE : PIC ABSOLUTE $A000:$0;
>PICFILE : FILE OF PIC;

>BEGIN
>GRON; {SET TO 640X480/16 MODE}
>SETCOLOR(WHITE);
>CIRCLE(320,200,100); {OR ANY DRAWING}
>ASSIGN(PICFILE,'PICTURE.DAT');
>REWRITE(PICFILE);
>WRITE(PICFILE,PICTURE);
>CLOSE(PICFILE);
>END.

>{This method saves the 640x480/16 graphic screen, at least
>the pixels (not the colors).)

Yes, if the display happens to be in correct read mode etc. That is very
ugly way to do things.

Quote
>But this method does not
>work if "gron" sets the graphic into 640x480/256 color
>mode. Why? Thanks. Joe}

The 256 color display is very different. Instead of bitmapping, color
planes etc. it is simply one byte per pixel. Because such takes much
address space bank switching is needed to handle the high part of the
address. The banks are switched either by hardware programming or by
VESA BIOS calls.

Now if you use Graph, you can use GetImage to read the image and
putimage to write it back to screen. Since those handle only 64K at a
time you need to handle the image as parts. Use Imagesize() to check
how much memory one horizontal line takes, then divide 65535 by that to
get the number of lines you can handle at one call.

In fact I have written something like that. I cannot guarantee anything
on it though. Note one needs to be in same mode during saving and
loading. The file has to be opened for proper mode. Also there is no
error handling.

Unit GrSave;

interface

uses graph;

Procedure Savescreen(var fp:file);
Procedure LoadScreen(var fp:file);

implementation

const maxb=65500;

type Block=record
              x:word;
              y:word;
              buffer:byte;
           End;

Procedure GetBlocksize(var rows:word; var size:word);
var d:word;
begin
  rows:=getmaxy+1;
  d:=0;
  repeat
    inc(d);
    rows:=(getmaxx+1+d div 2) div d;
    size:=imagesize(0,0,getmaxx,rows-1);
  until (size>0) and (size<maxb)
End;

Procedure Savescreen(var fp:file);
var p:^block;
    rows,size:word;
    first,last:word;
begin
  GetBlocksize(rows,size);
  getmem(p,size+4);
  last:=rows-1;
  first:=0;
  rewrite(fp,1);
  blockwrite(fp,size,2);
  repeat
    getimage(0,first,getmaxx,last,p^.buffer);
    p^.x:=0;
    p^.y:=first;
    blockwrite(fp,p^,size+4);
    inc(first,rows);
    inc(last,rows);
    if (last>getmaxy) and (last>=first) then begin
         last:=getmaxy;
         size:=imagesize(0,first,getmaxx,last);
    End;
  until first>getmaxy;
  freemem(p,size+4);
  close(fp);
End;

Procedure LoadScreen(var fp:file);
var p:^block;
    size:word;
    bytesread:word;
begin
  reset(fp,1);
  blockread(fp,size,2);
  getmem(p,size+4);
  blockread(fp,p^,size+4,bytesread);
  while bytesread>0 do begin
    putimage(p^.x,p^.y,p^.buffer,NormalPut);
    blockread(fp,p^,size+4,bytesread);
  End;
  freemem(p,size+4);
  close(fp);
End;

end.

Osmo

Other Threads