[comp.sys.mac.programmer] Help with ScrnBase

mil@mendel.acc.Virginia.EDU (Maria I. Lasaga) (08/24/90)

Can anyone tell me why the following code bombs?  Any clues
would be appreciated.

Essentially, I am trying to switch between the main and alternate video 
buffers of an SE. (I know that newer Mac models don't have this option, but 
I need to use it for a very specific application.)  I am trying to get
around using assembly language because I haven't used it in a while and am 
a bit rusty, and because I don't have the time to relearn it.
(IM III-20 suggests how one might alternate between the main and
alternate video buffers in assembly language, but I can't make sense of
it.)  

So here's the code that bombs.  The machine just freezes.  I assume I 
am overwriting parts of memory I shouldn't, but I don't get how I am
doing this:




var
   offscreen: grafport;
  mypointer: ptr;
  mybitmap: bitmap;
  myaddress: longint;

begin

{--offscreen bitmap created here--}


 eraserect(theport^.portrect);     {  clearing the area of memory...  }

 myaddress := $727;     {starting location for alternate memory buffer on SE}
 mybitmap.baseaddr := @myaddresvkcPmybitmap.rowbytes := offscreen.portbits.rowbytes;
 mybitmap.bounds := offscreen.portbits.bounds;
 copybits(offscreen.portbits, mybitmap, 
         offscreen.portrect, offscreen.portrect, srccopy, nil);
		 
                  {copies an image previously drawn in an offscreen portrect}
				  
 myaddress := $824;   {supposedly the location of the global variable,}
                      {ScrnBase, that holds the address of the main screen }
                      {buffer. }
					  
 mypointer := @myaddress;
 mypointer^ := $727;   {Attempt to set ScrnBase to the address of the }
                       {alternate screen buffer.}
end;




----------------------------------------------------------------------- 
Maria I. Lasaga
Dept. of Psychology
Gilmer Hall
University of Virginia
Charlottesville, Virginia 22903                   mil@virginia.bitnet
----------------------------------------------------------------------- 

mil@mendel.acc.Virginia.EDU (Maria I. Lasaga) (08/24/90)

(Sorry.  Noise on the line messed up the code in the previous listing.)

Can anyone tell me why the following code bombs?  Any clues
would be appreciated.

Essentially, I am trying to switch between the main and alternate video 
buffers of an SE. (I know that newer Mac models don't have this option, but 
I need to use it for a very specific application.)  I am trying to get
around using assembly language because I haven't used it in a while and am 
a bit rusty, and because I don't have the time to relearn it.
(IM III-20 suggests how one might alternate between the main and
alternate video buffers in assembly language, but I can't make sense of
it.)  

So here's the code that bombs.  The machine just freezes.  I assume I 
am overwriting parts of memory I shouldn't, but I don't get how I am
doing this:




var
  oldport: grafptr;
   offscreen: grafport;
  mypointer: ptr;
  mybitmap: bitmap;
  myaddress: longint;

begin

{--offscreen bitmap created here--}


 eraserect(theport^.portrect);     {  clearing the area of memory...  }

 myaddress := $727;     {starting location for alternate memory buffer on SE}
 mybitmap.baseaddr := @myaddress;
 mybitmap.rowbytes := offscreen.portbits.rowbytes;
 mybitmap.bounds := offscreen.portbits.bounds;
 copybits(offscreen.portbits, mybitmap, 
         offscreen.portrect, offscreen.portrect, srccopy, nil);
		 
                  {copies an image previously drawn in an offscreen portrect}
				  
 myaddress := $824;   {supposedly the location of the global variable,}
                      {ScrnBase, that holds the address of the main screen }
                      {buffer. }
					  
 mypointer := @myaddress;
 mypointer^ := $727;   {Attempt to set ScrnBase to the address of the }
                       {alternate screen buffer.}
end;




----------------------------------------------------------------------- 
Maria I. Lasaga
Dept. of Psychology
Gilmer Hall
University of Virginia
Charlottesville, Virginia 22903                   mil@virginia.bitnet
----------------------------------------------------------------------- 

jackiw@cs.swarthmore.edu (Nick Jackiw) (08/24/90)

mil@mendel.acc.Virginia.EDU (Maria I. Lasaga) writes:
> Can anyone tell me why the following code bombs?  Any clues
> would be appreciated.

DISCLAIMER: I've never played with ScrnBase and don't, off the
top of my head, know how to do it.  The following observations
are "clues"--not answers.

	> 
	> var
	>   oldport: grafptr;
	>    offscreen: grafport;
	>   mypointer: ptr;

"Ptr" is defined in the Memory Manager as ^SignedByte.  You are
trying to stuff either a word or a longword into myPointer.
Depending on your compiler, you may just be sticking the low-order
byte of this word or longword into myPointer^.  Try instead
declaring myPointer as either ^longint or ^integer, depending
on whether you want to write four bytes or two.

	>   mybitmap: bitmap;
	>   myaddress: longint;
	> 
	> begin
	> 
	> {--offscreen bitmap created here--}
	> 
	> 
	>  eraserect(theport^.portrect);    {  clearing the area of memory...  }
	> 
	>  myaddress := $727;     {starting location for alternate memory buffer on SE}
	>  mybitmap.baseaddr := @myaddress;

I highly doubt that location $727 is the base address of an alternate
memory buffer.  Why?  Because a B&W 9" screen is about 20K worth of
data, and the area between $727 and $727+20K is filled with important
low-memory globals.  Not exactly information you want to be drawing
pictures over.  Could location $727 *contain* the address of the
alternate screen buffer?  If so, you'll want to set myBitmap.baseAddr
to longintPtr($727)^, instead of to $727 itself.

	>  mybitmap.rowbytes := offscreen.portbits.rowbytes;
	>  mybitmap.bounds := offscreen.portbits.bounds;
	>  copybits(offscreen.portbits, mybitmap, 
	>          offscreen.portrect, offscreen.portrect, srccopy, nil);
	> 		 
	>          {copies an image previously drawn in an offscreen portrect}
	> 				  
	>  myaddress := $824; {supposedly the location of the global variable,}
>                       {ScrnBase, that holds the address of the main screen }
>                       {buffer. }
> 					  
	>  mypointer := @myaddress;
	>  mypointer^ := $727;  {Attempt to set ScrnBase to the address of the }
	>                        {alternate screen buffer.}
	> end;

This stuff is wrong for the above reasons.  You're setting location $824
to value $727, and I suspect you want to set location $824 to value of
location $727.  If not, as soon as you write data, the 20K following location
$727 is going to be scrambled--including, of course, location $824.

Hope this puts you on the right track.



-- 
------------------------
Nick Jackiw		jackiw@cs.swarthmore.edu  "Just break out the
Visual Geometry Project	jackiw@swarthmr.bitnet     rum so we seem natural!"
Swarthmore College, PA 19081-1397				-F. Franklin

hawley@adobe.COM (Steve Hawley) (08/24/90)

In article <1990Aug23.171125.20436@murdoch.acc.Virginia.EDU> mil@mendel.acc.Virginia.EDU (Maria I. Lasaga) writes:
>
>Can anyone tell me why the following code bombs?  Any clues
>would be appreciated.

Here is some C code I wrote a while ago to do page swapping.
I have seen it work on a Mac Plus with 1M & 2M, a Mac SE with 2M and a
Mac SE30.  It doesn't do any sort of sanity checks for color QD, Mac II
family machines or wierdo screen sizes (you want to add all this, trust me)
so it will crash unceremoniously under such conditions.  It will also not
get along well with the MultiFinder (surprise, surprise).

You can probably convert it to Pascal:

/* PageSwap.h */
#define vPage2	6
#define vBase	0xefe1fe /* from IM III */
#define vBufA (512*15) /* ditto */
/* I wanted the swaps to be 1 instruction macro, not a function call.
 * You can probably do a similar with an inline Pascal definition.
 */
#define ScreenOne() asm { BSET #vPage2,vBase+vBufA }
#define ScreenTwo() asm { BCLR #vPage2,vBase+vBufA }
#define PAGEDIF 0x8000	 /* difference between 2 screen pages in memory
			  * This should probably be calculated not defined
			  * so we have a hope of working on big monitors.
			  */

extern GrafPort scrnPort; /* global GrafPort and BitMap */
extern BitMap ScreenMap;
extern unsigned int rwords, rbytes, maxv; /* screen dimensions */
/* end of PageSwap.h */

/* PageSwap.c */
#include "PageSwap.h"

GrafPort scrnPort;
BitMap ScreenMap;
unsigned int *page1, *page2;
unsigned int rwords, rbytes, maxv;

SetUpDouble()
{
	/* code to set up double buffering.  Your program will most
	 * certainly crash without this.
	 */
	int ref;
	Handle ahandle;
	Str255 ApplName;

	if (CurPageOption != -1) { /* no double buffering, restart me */
		GetAppParms(ApplName, &ref, &ahandle); /* who am i? */
		Launch(-1, ApplName);  /* start me with double buffering */
	}
	else { /* have 2 buffers */
		OpenPort(&scrnPort);
		page1 = (unsigned int *)scrnPort.portBits.baseAddr;
		/* don't ask me why I did this in assembly language.
		 * It probably seemed like a good idea at the time.
		 */
		asm {
			move.l page1, d0
			sub.l #PAGEDIFF, d0
			move.l d0, page2
		}
		maxv = scrnPort.portBits.bounds.bottom -
			scrnPort.portBits.bounds.top;
		rbytes = scrnPort.portBits.rowBytes;
		rwords = rbytes/2;
		ScreenMap = scrnPort.portBits;
		ScreenMap.baseAddr = (Ptr)page2;
	}
}

SwapPages()
{
	/* Flip the pages and set the offscreen map to the invisible one.
	 */
	if (ScreenMap.baseAddr == (Ptr)page1) {
		ScreenOne();
		ScreenMap.baseAddr = (Ptr)page2;
	}
	else {
		ScreenTwo();
		ScreenMap.baseAddr = (Ptr)page1;
	}
}

SetPortBitsToCurrentPage()
{
	/* Let QuickDraw know where we are.  I don't do this explicitly,
	 * because you might not want the overhead if you are writing your
	 * own BitBlit code (like I did).
	 */
	 SetPortBits(&ScreenMap);
}

MakeMeSane()
{
	/* restore some sanity in the world.
	 */
	ScreenOne();
	ScreenMap.baseAddr = (Ptr)page1;
	SetPortBitsToCurrentPage();
}
/* end of PageSwap.c */


/* main.c -- some example code */
#include "PageSwap.h"

main()
{
	Rect r;

	InitGraf(&thePort);

	HideCursor();
	SetUpDouble();
	SetPortBitsToCurrentPage();

	r = ScreenMap.bounds

	/* hey look!  Quickdraw still works! */
	PenPat(ltGray);
	PaintRect(&r);

	SwapPages();
	SetPortBitsToCurrentPage();

	PenPat(black);
	PaintRect(&r);

	while(!Button()) {
		SwapPages();
	}
	MakeMeSane();
	ShowCursor();
}
/* end of main.c */

/* Typos are not my fault!  :') */
Steve Hawley
hawley@adobe.com
-- 
"I can always telephone, but I can't tell it much."
	-Roy Blount