I'm trying to surpass what I did with the machine during my childhood by
taking up the Inside Macintosh documentation and trying to program stuff
in C. I've set up a webpage for my progress - it's only begun. Just
forget the very simplistic design of the webpage - I didn't and don't
want to spend much time on it.
I have a lot of questions about impasses I'm currently having right now.
Some of it is simple, some of it is less. Here's a short first list:
1) Hiding the menu bar altogether. I don't want to toggle it with
mouse-overs, I want it gone. How? It should be really simple, but I'm
having 0 success finding this simple information on the web or in my books.
2) Opening a PICT file with the System 6 (and under) call "SFGetFile"
(rather than "StandardGetFile"). I'm writing the value of what that
function returns on the screen, and so far it's been negative codes.
StandardGetFile (for System 7 and up) returns no values (it's a "pascal
void" function).
3) The philosophy behind implementing machine-independant timers - this
will be essential for game programming. I don't want it to go too fast
for more recent machines.
4) Offscreen bitmaps/bitimages, or offscreen grafport. How do you do it
with whatever is available in the first three Inside Macintosh books, if
at all possible. Are GWorld stuff specific to System 7 and up? I don't
want to use that. The most aggravating thing with the function
DrawPicture, is that I've been unable to draw that image anywhere but on
the screen. I would like to be able to deal with PICT resources, draw
them offscreen on some bit images and then be able to use the fast
CopyBits function as I wish.
That is all for now. I hope there are some veteran programmers among
myou. If not, well at least I might enjoy a public for my tests and games!
> I've recently entered an intense bout of nostalgia and digged up my old
> Mac Plus at my parents' house. To my great horror, I saw that I missed
> about 20% of my disks, sometimes it would be only one of a series of
> multiple disks for some games. Really frustrating.
>
> I'm trying to surpass what I did with the machine during my childhood by
> taking up the Inside Macintosh documentation and trying to program stuff
> in C. I've set up a webpage for my progress - it's only begun. Just
> forget the very simplistic design of the webpage - I didn't and don't
> want to spend much time on it.
>
> 68k.xt10.net
>
> I have a lot of questions about impasses I'm currently having right now.
> Some of it is simple, some of it is less. Here's a short first list:
>
> 1) Hiding the menu bar altogether. I don't want to toggle it with
> mouse-overs, I want it gone. How? It should be really simple, but I'm
> having 0 success finding this simple information on the web or in my books.
There are a few ways to do it. Availability and appropriateness varies
with the OS release you're working under. For something that you're
doing on a Plus, probably you're looking to mess with the MBarHeight
system global.
> 2) Opening a PICT file with the System 6 (and under) call "SFGetFile"
> (rather than "StandardGetFile"). I'm writing the value of what that
> function returns on the screen, and so far it's been negative codes.
> StandardGetFile (for System 7 and up) returns no values (it's a "pascal
> void" function).
What kinds of negative codes?
> 3) The philosophy behind implementing machine-independant timers - this
> will be essential for game programming. I don't want it to go too fast
> for more recent machines.
Look for info on something called the Time Manager.
> 4) Offscreen bitmaps/bitimages, or offscreen grafport. How do you do it
> with whatever is available in the first three Inside Macintosh books, if
> at all possible.
If you're on a Plus, you can at least use Volume 4 as well. But you
don't need to for this. You allocate a GrafPort, set it as current, draw
to your heart's content, and then use CopyBits to get it to the screen.
You'll want to learn to use VBL interrupts to schedule your screen
writes.
> Are GWorld stuff specific to System 7 and up?
Yep.
> I don't want to use that. The most aggravating thing with the function
> DrawPicture, is that I've been unable to draw that image anywhere but on
> the screen. I would like to be able to deal with PICT resources, draw
> them offscreen on some bit images and then be able to use the fast
> CopyBits function as I wish.
>
> That is all for now. I hope there are some veteran programmers among
> myou. If not, well at least I might enjoy a public for my tests and games!
By happenstance, I'm looking to get rid of my old Mac programming docs
and am willing to part with them for the cost of shipping. In addition
to listing a full set of IM on eBay, I've got - still unlisted - a few
non-Apple books like Dave Mark's introductory books. They were excellent
for their day.
--
Standard output is like your butt. Everyone has one. When using a bathroom,
they all default to going into a toilet. However, a person can redirect his
"standard output" to somewhere else, if he so chooses. - Jeremy Nixon
> 1) Hiding the menu bar altogether. I don't want to toggle it with
> mouse-overs, I want it gone. How? It should be really simple, but I'm
> having 0 success finding this simple information on the web or in my books.
It isn't. I think a command for hiding the menu bar wasn't added until
7.5 or so. Before that, you had to use GetMBarHeight() to measure the
menu bar, calculate the rect based on the main screen rect, and then
"punch it out" of the "gray region".
> 2) Opening a PICT file with the System 6 (and under) call "SFGetFile"
> (rather than "StandardGetFile"). I'm writing the value of what that
> function returns on the screen, and so far it's been negative codes.
> StandardGetFile (for System 7 and up) returns no values (it's a "pascal
> void" function).
No idea what you're talking about. You may want to show us some code.
Though I have to admit I never really did any programming until I had
7.0.
> 3) The philosophy behind implementing machine-independant timers - this
> will be essential for game programming. I don't want it to go too fast
> for more recent machines.
Could you clarify? I usually just remember the time I last did
something (GetTicks() or TickCount() or whatever it was called) and then
did a compare, not doing anything if the most recent event was too
recent. You can do this at idle time, or if that doesn't yield the
correct performance, do it in a tight loop and call GetNextEvent() or
WaitNextEvent() only every n-th time around.
But on a Plus, any timing code you insert may already cause a slowdown
that may be noticeable (this is from my memories of my first attempts at
doing color graphics with an LC I, so maybe I just did something else
wrong back then).
> 4) Offscreen bitmaps/bitimages, or offscreen grafport. How do you do it
> with whatever is available in the first three Inside Macintosh books, if
> at all possible. Are GWorld stuff specific to System 7 and up? I don't
> want to use that. The most aggravating thing with the function
> DrawPicture, is that I've been unable to draw that image anywhere but on
> the screen. I would like to be able to deal with PICT resources, draw
> them offscreen on some bit images and then be able to use the fast
> CopyBits function as I wish.
That's a little tricky. You might want to look for old source code from
that time. I think the Dartmouth XCMD collection HyperCard stack
contained source code for XCMDs that created a GrafPort of their own and
used that as an offscreen drawing canvas. But I barely remember that as
I just used GWorlds instead.
> That is all for now. I hope there are some veteran programmers among
> myou. If not, well at least I might enjoy a public for my tests and games!
Well, veteran would be too much said for me, but I *did* come across
the occasional bit of System 6 code.
Cheers,
-- Uli
> There are a few ways to do it. Availability and appropriateness varies
> with the OS release you're working under. For something that you're
> doing on a Plus, probably you're looking to mess with the MBarHeight
> system global.
Oh right! Forgot to tell him that: change the MBarHeight (and restore
it once you quit, or you'll screw up the OS), and change the gray region
not to include the menu bar anymore (and also restore that). If you only
change the gray region, you get a clickable but invisible menu bar, i.e.
like MacroMind Director had it when you set the stage to be full screeen.
Going, going, gone,
-- Uli
http://www.zathras.de
1) I do have IM volume 4, also from one of the mid-eighties editions.
2) Here's a source code of my attempt to use SFGetFile. Just overlook
the "NewLoadMethod" which will attempt to use StandardGetFile. It's
just not finished, or even started yet.
"OldLoadMethod" simply brings up a SFGetFile dialog box, allows you to
load PICT files and *should* draw it. I modified my code from the
first time around (that old version is lost, unfortunately) but it
seems now that it freezes somewhere in "OldLoadMethod" before it
completes its execution.
Source code in browser: http://68k.xt10.net/code/graphx6.c.txt
Source code in a .sit file, along with a dummy PICT file:
http://68k.xt10.net/files/SFGetFile.sit
3) About what I'm trying to do with these "time managers" like you
call them, is to simply produce "game events" where something happens
every 1 second, for example, and I want it machine independant (of
course if too much is computed on a Mac Plus, perhaps the program will
miss its mark, but I'll be the manager of that).
> 3) About what I'm trying to do with these "time managers" like you
> call them, is to simply produce "game events" where something happens
> every 1 second, for example, and I want it machine independant (of
> course if too much is computed on a Mac Plus, perhaps the program will
> miss its mark, but I'll be the manager of that).
You are looping, calling GetNextEvent. One of the fields of the
EventRecord is the .when field, which is the number of ticks since the
machine was booted. A tick is 1/60th of a second. The .when field will
overflow eventually, but it is extremely unlikely that your Mac will be
up that long, so don't worry about it.
to schedule something for a second after now:
target = TickCount() + 60;
....
GetNextEvent(...
HandleEvent(e);
if(target < e.when){
DoSomething();
target = 0xFFFFFFFF;
}
> 2) Here's a source code of my attempt to use SFGetFile. Just overlook
> the "NewLoadMethod" which will attempt to use StandardGetFile. It's
> just not finished, or even started yet.
SFTypeList myFileTypes;
myFileTypes[0]='PICT';
I'm not sure (haven't got the headers here), but judging from other
parts of the Classic Toolbox, SFTypeList is declared as OSType*,
OSType[] or OSType[0]. Thus, you're probably stomping your stack here.
Try:
OSType[1] myFileTypes;
myFileTypes[0] = 'PICT';
Also, I'm not sure about the StdProcs stuff you are doing there. What is
this trying to achieve? To draw a picture, you don't need it.
Confused,
-- Uli
http://www.zathras.de
Ok, on the Mac Plus, events seem to follow that TickCount standard,
where 60 ticks = 1 second. When I tried it in Basilisk II, events
scheduled to trigger every second where going as fast as possible. My
event was a SysBeep(1). I realize this function call behaves
differently between these OS but there's clearly also a difference in
the passage of time between these two environments. I don't think I'll
support System 7 and up if it turns out to be too much of a hassle.
Did you mean OSType myFileTypes[1]?
OSType[1] myFileTypes doesn't compile.
Either way, that piece of the code works, because SFGetFile clearly
only displays 'PICT' files in the file open dialog.
Also, the customized Proc for reading or opening a PICT confuses me
too; I tried to compile an example I took from the web. I can't find
it again, but it looked a lot like what is described in this page of
the online IM: http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-334.html#MARKER-9-60
I tried commenting out everything related to this customized
procedure, but it still doesn't work.
Supporting System 7 shouldn't be a hassle at all. Can you clarify what
you tried to do and what you observed?
> Ok, on the Mac Plus, events seem to follow that TickCount standard,
> where 60 ticks = 1 second. When I tried it in Basilisk II, events
> scheduled to trigger every second where going as fast as possible. My
> event was a SysBeep(1). I realize this function call behaves
> differently between these OS but there's clearly also a difference in
> the passage of time between these two environments. I don't think I'll
> support System 7 and up if it turns out to be too much of a hassle.
On some versions of the system, SysBeep(1) blocks until the sound
completes. If you have a long sound, this will throw your timing off.
> Supporting System 7 shouldn't be a hassle at all. Can you clarify what
> you tried to do and what you observed?
I'll illustrate with a compiled program.
Source code in browser: http://68k.xt10.net/code/BeepClock.c.txt
Program in .sit file: http://68k.xt10.net/files/BeepClock.sit
Try it in both settings - press a key to exit the program. (emulator
or real machines, both have worked on my end and reproduce the results
listed below:)
System 6: The program simply tries to emit a SysBeep(1) (shortest
possible system "beep", I suppose) every 60 ticks. The exact condition
is this one: whenever GetTick()/60 != 0 && GetTick()%60=0, so that it
falls on round numbers of seconds. The short duration of SysBeep is
there to ensure that the actual sound won't last longer than a second
so as to not skip any second. I was worried the loop might sometimes
erratically take more time and we would stop hearing a SysBeep(1) at
some times, but it seems to be fairly solid.
System 7: The system beep is whatever sound is set in the control
panel. The program just seems to ignore how GetTick works and simply
beeps as frequently as possible.
> Gregory Weston <gwesto...@CAPSattbi.com> wrote in message
> news:<gwestonREMOVE-DFE...@netnews.comcast.net>...
>
> > Supporting System 7 shouldn't be a hassle at all. Can you clarify what
> > you tried to do and what you observed?
>
>
> I'll illustrate with a compiled program.
>
> Source code in browser: http://68k.xt10.net/code/BeepClock.c.txt
> Program in .sit file: http://68k.xt10.net/files/BeepClock.sit
>
> System 7: The system beep is whatever sound is set in the control
> panel. The program just seems to ignore how GetTick works and simply
> beeps as frequently as possible.
By System 7, beeps were asynch, so the first time it hits "wutup.when %
60 == 0", it beeps. That takes nearly no time at all (less than a tick)
and so it comes back and since the time hasn't advanced more than a
tick, it beeps a second time, and perhaps so on for third or fourth time
as well. At some point, wutup.when % 60 isn't 0, but several beeps have
been "queued up", and it'll come back to wutup.when % 60 == 0 before the
beeps have completed from the first time through, it'll queue up some
more, etc...
How about something more like:
nextTime = 0;
while (!exitflag) {
if (TickCount() > nextTime) {
nextTime = TickCount() + 60;
SysBeep(1);
}
GetNextEvent(everyEvent, &wutup);
if (wutup.what == keyDown) break;
}
> Did you mean OSType myFileTypes[1]?
> OSType[1] myFileTypes doesn't compile.
Uh, yes, sorry about that.
> Either way, that piece of the code works, because SFGetFile clearly
> only displays 'PICT' files in the file open dialog.
I just Googled, and it looks like SFTypeList is defined as OSType[4],
so I guess this is moot.
But anyway, if it *had* been OSType[0] instead, it wouldn't have
mattered whether you get only PICT files. You'd still have been stomping
on stack space that didn't belong to you, and thus a crash happening
later could have been triggered by that. That's why memory errors are so
hard to fix. The point at which they happen may be a dozen lines (or
even hours) later than the point at which the memory was cobbled in the
first place.
> Also, the customized Proc for reading or opening a PICT confuses me
> too;
Wait, are you opening a PICT file, or what are you trying to do? PICT
_resources_ are usually loaded by doing:
PicHandle thePic = GetPicture(128);
Where 128 is the ID number of whatever resource you want to load. Now
you have a PicHandle that you can get rid of using KillPicture(), draw
using DrawPicture() etc.
What you have to watch out for here is that the "current resource file"
must be set to the file containing your PICT. Your application's res
fork is opened at startup by default, but if you're opening resource
files of your own, you'll have to restore it later.
If you're loading a PICT file, you have to skip past the 512 byte header
every PICT file contains in its data fork. The StdProcs stuff is
completely unnecessary in this case, AFAIK.
> What you have to watch out for here is that the "current resource file"
> must be set to the file containing your PICT. Your application's res
> fork is opened at startup by default, but if you're opening resource
> files of your own, you'll have to restore it later.
>
> If you're loading a PICT file, you have to skip past the 512 byte header
> every PICT file contains in its data fork. The StdProcs stuff is
> completely unnecessary in this case, AFAIK.
I've already successfully loaded up resource files and displayed
pictures from them. I'm trying to do it with the data fork of pictures
I've done in MacDraw or other similar programs. I know that there is a
512 byte header that I have to skip, but for the life of me, I can't
figure out why the code doesn't work. I've tried to simplify it as
much as I could, and it never seems to work. The first thing I tried
to do was to cut off that custom StdProcs thing, which in retrospect,
I think it was done as a way to break the size limitations of PICT
files (which is 32k IIRC).
The crucial step in FSRead is to decide the kind of pointer to the
reading buffer that you'll pass as an argument to FSRead. Should it be
the address of a PicHandle? The address to a PicPtr? The address to a
Picture?
I've also tried to do the reverse: create a dummy "generic file" in
which I'd write a string of text with FSWrite. It doesn't even work.
Can someone out there write the shortest program they can that
demonstrate FSOpen, FSRead and FSWrite? I'd be very grateful and it
would restore my faith in mac C.
Thanks! ;)
> I've already successfully loaded up resource files and displayed
> pictures from them. I'm trying to do it with the data fork of pictures
> I've done in MacDraw or other similar programs. I know that there is a
> 512 byte header that I have to skip, but for the life of me, I can't
> figure out why the code doesn't work.
Can't get your old message to display right now, but you are using
FSetPos() or whatever the call was named, with fsFromStart and a 512
offset, right? And then you'd FSGetEOF() or FSGetLength() or
FSGetLogicalEOF() or whatever it was called to get the file size, and
read that many bytes -512.
> I've tried to simplify it as
> much as I could, and it never seems to work. The first thing I tried
> to do was to cut off that custom StdProcs thing, which in retrospect,
> I think it was done as a way to break the size limitations of PICT
> files (which is 32k IIRC).
PicHandle itself may have a limit of 32k if you're doing Basic
Quickdraw (as opposed to Color Quickdraw), which sounds like the case
for a Mac Plus.
> The crucial step in FSRead is to decide the kind of pointer to the
> reading buffer that you'll pass as an argument to FSRead. Should it be
> the address of a PicHandle? The address to a PicPtr? The address to a
> Picture?
You'll need to allocate a PicHandle of the proper size. A Handle is
basically a pointer to a pointer (though not every pointer to a pointer
is a Handle), so to use it like any other pointer, you'll have to
de-reference it once. So *myPicHandle would be what you'd pass to FSRead
if it takes a Ptr.
> I've also tried to do the reverse: create a dummy "generic file" in
> which I'd write a string of text with FSWrite. It doesn't even work.
You'll have to create the file and open it before you can write to it.
> Can someone out there write the shortest program they can that
> demonstrate FSOpen, FSRead and FSWrite? I'd be very grateful and it
> would restore my faith in mac C.
I don't have the old MacOS headers anywhere in reach, but if you could
provide me with the prototypes for the open/create/read/write/getlength
etc. functions I could probably write something that should be very
close to correct code.
gone to memorize his lines now,
-- Uli
http://www.zathras.de
> I've already successfully loaded up resource files and displayed
> pictures from them. I'm trying to do it with the data fork of pictures
> I've done in MacDraw or other similar programs.
Are you sure those files are PICT files? MacDraw's native format was not
PICT.
> Can someone out there write the shortest program they can that
> demonstrate FSOpen, FSRead and FSWrite? I'd be very grateful and it
> would restore my faith in mac C.
WARNING: No compiler has ever seen this code.
WARNING: I copy-pasted this from old archives.
WARNING: this code will contain errors (missing #includes, at least)
short OldFile()
{
SFTypeList myTypes;
SFReply reply;
short result = 0;
Point where = {50, 50};
myTypes[ 0] = 'TEXT';
SFGetFile( where, "\pSelect a file", 0L, 1, myTypes, 0L, &reply);
if( reply.good)
{
FSOpen( reply.fName, reply.vRefNum, &result);
}
return result;
}
int main( int argc, char * argv[])
{
int result = EXIT_FAILURE;
const short file = OldFile();
if( file != 0)
{
char buffer[ 20];
long count = sizeof( buffer);
// Real programs do error-checking here
(void)SetFPos( file, fsFromStart, 0);
(void)FSRead( file, &count, buffer);
(void)SetFPos( file, fsFromStart, sizeof( buffer));
(void)FSWrite( file, &count, buffer);
(void)FSClose( file);
result = EXIT_SUCCESS;
}
return result;
}
Reinder
#include <Quickdraw.h>
#include <Events.h>
#include <Windows.h>
#include <StandardFile.h>
#include <OSUtils.h>
#define EXIT_FAILURE 0
#define EXIT_SUCCESS 1
short OldFile(void);
short OldFile()
{
SFTypeList myTypes;
SFReply reply;
short result=0;
Point where={50,50};
myTypes[0]='PICT';
SFGetFile(where,"\pSelect a file",0L,1,myTypes,0L,&reply);
if(reply.good)
{
FSOpen(reply.fName,reply.vRefNum,&result);
}
return result;
}
int main(int argc, char * argv[])
{
int result=EXIT_FAILURE;
PicHandle myPicture;
long count;
WindowRecord mywin;
WindowPtr mywinptr;
Rect r,windowrect;
EventRecord wutup;
short file;
InitGraf(&qd.thePort);
InitWindows();
InitCursor();
windowrect=qd.screenBits.bounds;
mywinptr=NewWindow(&mywin,&windowrect,"\p",true,2,(WindowPtr)-1,true,0);
SetPort(mywinptr);
FlushEvents(everyEvent,0);
file=OldFile();
if(file !=0)
{
count = sizeof(PicHandle);
SetFPos(file,fsFromStart,512);
FSRead(file,&count,*myPicture);
FSClose(file);
result=EXIT_SUCCESS;
}
HLock((Handle)myPicture);
r=(*myPicture)->picFrame;
DrawPicture(myPicture,&r);
HUnlock((Handle)myPicture);
while(!Button());
}
// The program doesn't display anything, but at least it doesn't crash
(in other words, the behavior is similar to several of my own
attempts).
pascal OSErr FSOpen(ConstStr255Param fileName, short vRefNum, short
*refNum);
pascal OSErr Create(ConstStr255Param fileName, short vRefNum, OSType
creator, OSType fileType);
pascal OSErr FSWrite(short refNum, long *count, const void *buffPtr);
pascal OSErr FSClose(short refNum);
getlength doesn't exist, I assume you want the function to get the
size of a structure or variable type? In all the examples I saw, they
simply use the std C sizeof(variable type)
Yes. It can save in its own proprietary format or in PICT.
> I've recently entered an intense bout of nostalgia and digged up my
> old Mac Plus at my parents' house. To my great horror, I saw that I
> missed about 20% of my disks, sometimes it would be only one of a
> series of multiple disks for some games. Really frustrating.
>
> I'm trying to surpass what I did with the machine during my childhood
> by taking up the Inside Macintosh documentation and trying to program
> stuff in C. I've set up a webpage for my progress - it's only begun.
> Just forget the very simplistic design of the webpage - I didn't and
> don't want to spend much time on it.
>
> 68k.xt10.net
>
> I have a lot of questions about impasses I'm currently having right
> now. Some of it is simple, some of it is less. Here's a short first
> list:
>
> 1) Hiding the menu bar altogether. I don't want to toggle it with
> mouse-overs, I want it gone. How? It should be really simple, but I'm
> having 0 success finding this simple information on the web or in my
> books.
Ah, a classic. There were a bunch of techniques, but IIRC, only one was
sanctioned in the Plus era. In fact there was a sample on the Apple
site. I bet it's still there. I think it just set the menu bar height
to zero. Sorry, not much help, but at least some of the names may
trigger someone's memory.
> 2) Opening a PICT file with the System 6 (and under) call "SFGetFile"
> (rather than "StandardGetFile"). I'm writing the value of what that
> function returns on the screen, and so far it's been negative codes.
> StandardGetFile (for System 7 and up) returns no values (it's a
> "pascal void" function).
Doesn't that really old PICT stuff still exist somewhere? I think there
was a folder of samples, with names like Draw Pict, Write Pict, Spool
Pict, etc. Not much help, again, but it's a start
>
> 3) The philosophy behind implementing machine-independant timers -
> this will be essential for game programming. I don't want it to go too
> fast for more recent machines.
>
> 4) Offscreen bitmaps/bitimages, or offscreen grafport. How do you do
> it with whatever is available in the first three Inside Macintosh
> books, if at all possible. Are GWorld stuff specific to System 7 and
> up? I don't want to use that. The most aggravating thing with the
> function DrawPicture, is that I've been unable to draw that image
> anywhere but on the screen. I would like to be able to deal with PICT
> resources, draw them offscreen on some bit images and then be able to
> use the fast CopyBits function as I wish.
The GWorld stuff was (among other things) a means to create offscreen
worlds without having to do it "by hand". Before them, you would
allocate a PixMap and initialize it Lots of color tables and paletttes
and stuff to mess with.
IIRC, there was a sample in develop #10 that introduced GWorlds (or is
that #1?) that showed the "by-hand" way for comparison. It was a lot of
PixMap detail that I can't remember at all. Once you made it, though,
it worked the same way.
>
> That is all for now. I hope there are some veteran programmers among
> myou. If not, well at least I might enjoy a public for my tests and
> games!
--
No sig, no neuroses
> >
> > 1) Hiding the menu bar altogether. I don't want to toggle it with
> > mouse-overs, I want it gone. How? It should be really simple, but I'm
> > having 0 success finding this simple information on the web or in my
> > books.
static short gs_dyMBar = 0;
static RgnHandle gs_hrgnMBar = NULL;
void HideMenuBar( void )
{
Rect rcMBar;
if ( gs_hrgnMBar == 0L ) {
gs_dyMBar = LMGetMBarHeight();
LMSetMBarHeight( 0 );
rcMBar = qd.screenBits.bounds;
rcMBar.bottom = rcMBar.top + gs_dyMBar;
gs_hrgnMBar = NewRgn();
RectRgn( gs_hrgnMBar, &rcMBar );
UnionRgn( LMGetGrayRgn(), gs_hrgnMBar, LMGetGrayRgn() );
PaintOne( nil, gs_hrgnMBar );
}
}
void ShowMenuBar( void )
{
if ( gs_hrgnMBar ) {
LMSetMBarHeight( gs_dyMBar );
DiffRgn( LMGetGrayRgn(), gs_hrgnMBar, LMGetGrayRgn() );
DisposeRgn( gs_hrgnMBar );
gs_hrgnMBar = 0L;
}
}
> if(file !=0)
> {
> count = sizeof(PicHandle);
> SetFPos(file,fsFromStart,512);
> FSRead(file,&count,*myPicture);
> FSClose(file);
> result=EXIT_SUCCESS;
> }
This is your problem. PicHandle is a variable-size data structure. You
can't just use sizeof(PicHandle) because that only gives you the
fixed-size part of the data structure.
> getlength doesn't exist, I assume you want the function to get the
> size of a structure or variable type? In all the examples I saw, they
> simply use the std C sizeof(variable type)
No, I meant something to get at the size of the file. Since PICTs are
variable-size, you have to calculate the size for the Handle by
subtracting 512 from the file's size. That function is what I'm looking
for. FSGetLength() or FSGetSize() or FSGetEOF() or GetEOF() could be
that function's name.
Also, I think you need to HLock()/HUnlock() the Handle around the call
to FSRead(). OTOH I think you don't need to HLock around DrawPicture().
You only need to lock when you're passing a once-dereferenced Handle
(the "master pointer") as a pointer into a function that may allocate
memory, because that may cause Handle's data to move and the master
pointer to change. OTOH DrawPicture() gets the Handle, and should
HLock() on its own when it needs it.
> UnionRgn( LMGetGrayRgn(), gs_hrgnMBar, LMGetGrayRgn() );
> PaintOne( nil, gs_hrgnMBar );
I don't have access to LMGetGrayRgn(). It's probably too recent. :/
Thanks anyway.
Look in your copy of LowMem.h for the address of the global for
the GrayRegion. It should be at address 0x09EE.
Ok, I immediately tried your changes.
I define this variable in main:
long fileend;
I lock my PicHandle before using FSRead.
at the beginning of that if(!file) block, I do:
GetEOF(file,&fileend);
count=fileend-512;
....
Still doesn't work. 8^(
> count = sizeof(PicHandle);
A PicHandle is a long so count is always 4.
Try this instead:
if(file !=0)
{
GetEOF(file,&count);
count -= 512;
myPicture = NewHandle(count);
SetFPos(file,fsFromStart,512);
HLock(myPicture);
FSRead(file,&count,*myPicture);
HUnlock(myPicture);
FSClose(file);
result=EXIT_SUCCESS;
}
If there's still a problem, add error checking and tell me what's
returned by the FS calls.
> If there's still a problem, add error checking and tell me what's
> returned by the FS calls.
It works! Thanks a lot!
Finally I'll be able to make my own proprietary animated sprite editor.
> Look in your copy of LowMem.h for the address of the global for
> the GrayRegion. It should be at address 0x09EE.
I don't even have a LowMem.h header, but I looked in Windows.h
instead. I did find a #define GetGrayRgn() (* (RgnHandle *) 0x09EE)
Also there is a #define GetMBarHeight() (* (short *)0x0BAA). There's
of course no SetMBarHeight (I've tried to search for variations on
that expression, to no avail). What's the most secure way of going
about and setting new values for these low memory locations?
Alright, with your help, and some help from somewhere else (on C
syntax), I made it work:
I declare:
short *setMBarHeight;
setMBARHeight=(short *)0x0BAA;
....
setMBarHeight=0;
---
I've learned that 64k ROM macs can't allow any change to the 20-pixel
menu bar.
So far, it's been working in System 6.0.8 (mac plus) and System 7.5
(LC575).
So....I'm going to have to fiddle around Gestalt global variables to
ensure that the program does NOT run when I'm on a too old, or too
recent machine.
Thanks everyone, this thread has been a great help for me.
> In article <e8740c97.04051...@posting.google.com>,
> micj...@videotron.ca (Mu0n) wrote:
>
> > if(file !=0)
> > {
> > count = sizeof(PicHandle);
> > SetFPos(file,fsFromStart,512);
> > FSRead(file,&count,*myPicture);
> > FSClose(file);
> > result=EXIT_SUCCESS;
> > }
>
> This is your problem. PicHandle is a variable-size data structure. You
> can't just use sizeof(PicHandle) because that only gives you the
> fixed-size part of the data structure.
Doesn't even give you that. sizeof(PicHandle) == 4.
> Also, I think you need to HLock()/HUnlock() the Handle around the call
> to FSRead().
Not IIRC.
My first, conservative, impulse would definitely have been to lock the
handle, but you've set me wondering. Is your reasoning that FSRead()
is unlikely to trigger any memory management in the *application*
heap? (Although of course it will probably trigger storms of activity
in other parts of the system.)
Toby
My "reasoning" is based on recollection. I specifically remembering
being able to do file I/O on unlocked relocatable memory. IM appears to
support that recollection.
> In article <d6ce4a6c.0405...@posting.google.com>,
> to...@telegraphics.com.au (Toby Thain) wrote:
>
> > Gregory Weston <gwesto...@CAPSattbi.com> wrote in message
> > news:<gwestonREMOVE-751...@netnews.comcast.net>...
> > > ...
> > > > Also, I think you need to HLock()/HUnlock() the Handle around the call
> > > > to FSRead().
> > >
> > > Not IIRC.
> >
> > My first, conservative, impulse would definitely have been to lock the
> > handle, but you've set me wondering. Is your reasoning that FSRead()
> > is unlikely to trigger any memory management in the *application*
> > heap? (Although of course it will probably trigger storms of activity
> > in other parts of the system.)
>
> My "reasoning" is based on recollection. I specifically remembering
> being able to do file I/O on unlocked relocatable memory. IM appears to
> support that recollection.
Actually calling FSRead with the dereferenced handle may not cause the
memory to move, but your code may do other things around the FSRead that
cause problems. You almost certainly don't want to use the same
unlocked, dereferenced handle more than once if you have any toolbox
calls between those calls. Generally, I treat both handles and pointers
with a great deal of paranoia, having spent far too many hours trying to
debug problems with errant handles and pointers in the past.
> > > > > Also, I think you need to HLock()/HUnlock() the Handle around the
> > > > > call to FSRead().
> > > >
> > > > Not IIRC.
> > >
> > > My first, conservative, impulse would definitely have been to lock the
> > > handle, but you've set me wondering. Is your reasoning that FSRead()
> > > is unlikely to trigger any memory management in the *application*
> > > heap? (Although of course it will probably trigger storms of activity
> > > in other parts of the system.)
> >
> > My "reasoning" is based on recollection. I specifically remembering
> > being able to do file I/O on unlocked relocatable memory. IM appears to
> > support that recollection.
>
> Actually calling FSRead with the dereferenced handle may not cause the
> memory to move, but your code may do other things around the FSRead that
> cause problems. You almost certainly don't want to use the same
> unlocked, dereferenced handle more than once if you have any toolbox
> calls between those calls.
Unless you're very familiar with the state of the toolbox on your target
machines, true. But I was responding in the context of this thread. The
dereferenced pointer wasn't cached in the code under discussion. It was
just a handle and an asterisk being passed in where a pointer was
wanted. That's safe for FSRead.
G
The first time I read about handles, I thought: why is this needed?
Then I saw that memory has to be compacted and moved a lot to make
room, as it was probably essential in the 128k mac days. But I also
was shocked to read that so and so function would require handle
locks, and for others, it wasn't necessary. There is no way I'll ever
spend time to learn the intricacies of each, I'll just deal as it
comes and forget about it in little time. Kind of makes me wonder why
the functions that require locks weren't designed to do that locking
themselves.
> Kind of makes me wonder why
> the functions that require locks weren't designed to do that locking
> themselves.
How would the toolbox know which handles to auto-lock and which to
move? Remember, the whole point was leave handles unlocked so the
memory manager could compact the heap as necessary. You're app should
only lock handles when it must. Having said that, I also grew paranoid
and info-overloaded and got into the habit of locking/unlocking on just
about all dereferences. If you're using a great language like c++, you
can write a simple stack-based HandleLock class to make life easy.
> Still doesn't work. 8^(
You know you actually made me dig out that backup of my old xDraw XCMD
for HyperCard? :-)
Anyway, here's some code excerpt that ready a PicHandle from a PICT
file. It's probably not quite useable on System 6, but maybe it'll help
you to find your problem:
Rect box;
Str255 fileName;
short vFileRef;
long vPicSize;
PicHandle pic = NULL;
QDProcsPtr oldProcs;
GrafPtr vPort;
OSErr vError;
// Some XCMD-specific setup (like getting the fileName) snipped.
// Open PICT file:
vError = FSOpen( fileName, 0, &vFileRef ); // This'll be different
// for you as well.
if( vError != noErr )
{
switch( vError )
{
case fnfErr:
ReturnString( "Error: File couldn't be found.",
REPLACE );
break;
default:
ReturnString( "Error: Couldn't open/create file (",
REPLACE );
ReturnLong( vError, APPEND );
ReturnString( ").", APPEND );
break;
}
return FALSE;
}
// Move past file header:
vError = SetFPos( vFileRef, fsFromStart, 512 );
if( vError != noErr )
{
FSClose( vFileRef );
ReturnString( "Error: Couldn't access read position (",
REPLACE );
ReturnLong( vError, APPEND );
ReturnString( ").", APPEND );
return FALSE;
}
vError = GetEOF( vFileRef, &vPicSize );
if( vError != noErr )
{
FSClose( vFileRef );
ReturnString( "Error: Couldn't calculate PICT size (", REPLACE );
ReturnLong( vError, APPEND );
ReturnString( ").", APPEND );
return FALSE;
}
vPicSize -= 512; // Don't count header.
// Make new Handle for PICT data:
pic = (PicHandle) NewHandle( vPicSize );
if( pic == NULL )
{
FSClose( vFileRef );
ReturnString( "Error: Not Enough memory to read picture (",
REPLACE );
ReturnLong( MemError(), APPEND );
ReturnString( ").", APPEND );
return FALSE;
}
// Read data into Handle:
HLock( (Handle) pic );
vError = FSRead( vFileRef, &vPicSize, (*pic) );
HUnlock( (Handle) pic );
if( vError != noErr )
{
DisposeHandle( (Handle) pic );
FSClose( vFileRef );
ReturnString( "Error: Couldn't read picture (", REPLACE );
ReturnLong( vError, APPEND );
ReturnString( ").", APPEND );
return FALSE;
}
It does seem clear that synchronous routines like FSRead are safe with
respect to the application heap (there is no way the application can
be re-entered and possibly trigger memory management). Perhaps my
impulse to lock comes from the necessity to do so if you're using
asynchronous I/O and/or you are expecting any interrupt-time callbacks
from the O/S (possibly interrupting a Memory Manager routine). I don't
think I've ever actually used async calls, or completion routines,
though :-)
T
The Mac Memory Manager and its double-indirection were meant to
mitigate the small RAM size and lack of MMU in the 68000 Macs; I
suppose heap compaction and semi-automatic purging seemed like good
ideas at the time. However the Lisa did have both more RAM and
hardware memory management. Off the top of my head I don't recall if
its software memory manager worked like the Mac's (anyone have Lisa
Pascal Workshop manuals online?)
<OT>
After the effort in keeping track of locking, unlocking and
dereferencing zillions of Mac Handles, the UNIX way - single
indirection, non-relocatable blocks, and per-process virtual address
space - comes as something of a relief. But you still have to plug
leaks (match malloc/free). When that palls, we can move on to garbage
collected systems (I have in mind Smalltalk-80 but Java counts too, I
suppose :)
PostScript had an interesting answer, objects allocated "forever"
within a nested save/restore context - just as resources used by a
UNIX process are completely reclaimed when it dies. Of course, it's
rare to have a PostScript "job" that runs forever (if it uses all
resources it will die, in the meantime monopolising a supposedly
shared printer/interpreter!), but one typically expects a UNIX daemon
to run indefinitely... and without leaks.
</OT>
T
FSRead/FSWrite are sync calls. They are defined to not move memory, and
can take as buffers unlocked handles. They are also defined not to
return until the IO completes.
The async versions of the IO routines (PBRead/PBWrite and friends)
require locked buffers because the IO happens "later" and your code
continues to run. You must ensure that until the IO completes that the
buffer remains locked and available.
-- Tom
> But you still have to plug
> leaks (match malloc/free).
I recommend c++ instead. Use the STL containers and stack-based smart
pointers such as boost::shared_ptr and you will never leak while never
having to match malloc/free or new/delete (and no autorelease pool
hacks).
*SNIP your probably working example*
I posted somewhere else in the thread that I finally made it work! But
thanks anyway, I still enjoyed your post, you've given me some coding
style ideas.
So, what was the problem you had? You know, to me the most interesting
part about these forums isn't helping solve people's problems, but
rather find out about new, interesting errors so I can recognize them
when I make them.
What was your mistake in your code, and how did you fix it?
Well, I guess I made somewhat of a newbie error. I assigned a 4-byte
buffer (which I'm now beginning to learn it's the standard size of all
handles...right?) to the piece of memory assigned to read in the data
- by simply making it sizeof(Handle). I corrected it by correctly
reading in the EOF count in a long variable, and substracting 512.
> Well, I guess I made somewhat of a newbie error. I assigned a 4-byte
> buffer (which I'm now beginning to learn it's the standard size of all
> handles...right?) to the piece of memory assigned to read in the data
> - by simply making it sizeof(Handle).
Well, that's almost right. You were measuring the size of the data type
"Handle", which is a pointer to a pointer. The size of a pointer in
MacOS right now is four bytes (the number of bytes needed to store a
memory address -- there are other platforms where a pointer can be
larger or smaller, but you only need to know that if you're writing
cross-platform code). Look at the definition of PicHandle:
typedef struct Picture Picture;
typedef Picture *PicPtr;
typedef Picture **PicHandle;
(or something to that effect), so what you should have done if Picture
wasn't a variably-sized data type would have been sizeof(Picture).
> I corrected it by correctly
> reading in the EOF count in a long variable, and subtracting 512.
That *is* what I told you to do all the time... you know, sometimes it
helps to listen to little Uli ;-)
Glad to know it's working now,
-- Uli
http://www.zathras.de
Yes, that's what I said :-)
T
>
> -- Tom