Amiga.org

Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: cycloid on May 10, 2003, 02:44:46 PM

Title: "Close Window" tutorial errors
Post by: cycloid on May 10, 2003, 02:44:46 PM
well i've scoured the "Amiga C Tutorial" website at liquido2.com for an email link but cant find one, so i'll post it here. i got my first amiga window runnig using the source but found some "issues" with the code that needed debugging, here they are:


>45                struct IntuiText *MyText;

this fills me with dread, surely that should be:

>45                struct IntuiText *MyText = new IntuiText;

but does that mean i have to "free" it when i shutdown?



>54                PrintIText( MyWindow->RPort, MyText, 0, 0 );

changing it to this:

>54                PrintIText( MyWindow->RPort, MyText, MyWindow->BorderLeft, MyWindow->BorderTop );

offsets it into the window's window bit. i learnt that by reading intuition.h :-)




>104           CloseLibrary( (struct Library *)IntuitionBase );

This caused shell lockups and all sorts of memory trouble, it worked cleanly when i made it:

>104           CloseLibrary( IntuitionBase );




also

>106
>107    return 0;
>108
>109 }


cycloid - willing and able C++ coder who's struggling through lack of documentation!
Title: Re: "Close Window" tutorial errors
Post by: Thomas on May 10, 2003, 06:14:24 PM
Quote

>45 struct IntuiText *MyText;

this fills me with dread, surely that should be:

>45 struct IntuiText *MyText = new IntuiText;

but does that mean i have to "free" it when i shutdown?


Of course you must allocate some memory if you use a pointer. But "new" is not the right thing here. I guess the tutorial is about C, not C++. Use AllocMem/FreeMem instead. Or use struct IntuiText MyText instead of *MyText.

Quote

>54 PrintIText( MyWindow->RPort, MyText, 0, 0 );

changing it to this:

>54 PrintIText( MyWindow->RPort, MyText, MyWindow->BorderLeft, MyWindow->BorderTop );

offsets it into the window's window bit. i learnt that by reading intuition.h


Just add the GimmeZeroZero flag, then Intuition does that for you.


Quote

>104 CloseLibrary( (struct Library *)IntuitionBase );

This caused shell lockups and all sorts of memory trouble, it worked cleanly when i made it:

>104 CloseLibrary( IntuitionBase );


But the former is correct. You should include , and to give the compiler the chance to inform you about wrong types.

Quote

cycloid - willing and able C++ coder who's struggling through lack of documentation!


Get the Amiga Developer CD. There is a lot of documentation on it and it is the *official* documentation. You really need it. Trial and error is not the right way to learn programming, because only documented features continue to work in future OS versions.

Bye,
Thomas
Title: Re: "Close Window" tutorial errors
Post by: Piru on May 10, 2003, 06:23:27 PM
Quote
You should include , and to give the compiler the chance to inform you about wrong types.

No. You MUST, *ABSOLUTELY MUST* use , and . Using clib is only asking for trouble.
Title: Re: "Close Window" tutorial errors
Post by: Sidewinder on May 10, 2003, 08:25:11 PM
@cycloid

Quote

well i've scoured the "Amiga C Tutorial" website at liquido2.com for an email link but cant find one, so i'll post it here. i got my first amiga window runnig using the source but found some "issues" with the code that needed debugging, here they are:


Thanks for the feedback.  Actually my email address (amiga@ssmnet.net) is found in the introduction (http://www.liquido2.com/tutorial/intro.html), but I should probably add it somewhere in every tutorial.

Quote

>45 struct IntuiText *MyText;

this fills me with dread, surely that should be:

>45 struct IntuiText *MyText = new IntuiText;

but does that mean i have to "free" it when i shutdown?


Good catch.  This should fill you with dread and is my bad for not catching it in the first place.  You are correct that the memory should be reserved for the IntuiText structure.  The Amiga way of doing this is:

struct IntuiText *MyText = (struct IntuiText *)AllocMem( sizeof( struct IntuiText ), 0L );

And yes, if you allocate  memory in this way you must free it after you are done using it by adding:

FreeMem( MyText, sizeof( struct IntuiText) );

to the end of that block.

An alternative would be to create a real IntuiText structure instead of a pointer to an IntuiText structure:

struct IntuiText MyText;

MyText.LeftEdge = 10;
MyText.TopEdge = 20;
MyText.IText = "Click the close button to exit!";
MyText.DrawMode = JAM1;
MyText.FrontPen = 1;
MyText.NextText = NULL;

PrintIText( MyWindow->RPort, &MyText, 0, 0 );

This is the change I will make to the tutorial source.

Quote

>54 PrintIText( MyWindow->RPort, MyText, 0, 0 );

changing it to this:

>54 PrintIText( MyWindow->RPort, MyText, MyWindow->BorderLeft, MyWindow->BorderTop );

offsets it into the window's window bit. i learnt that by reading intuition.h


Very true, but as mentioned already, adding a WA_GimmeZeroZero tag when defining the window will do the same automagically.

Quote

>104 CloseLibrary( (struct Library *)IntuitionBase );

This caused shell lockups and all sorts of memory trouble, it worked cleanly when i made it:

>104 CloseLibrary( IntuitionBase );


The code in the tutorial is correct for ANSI C compilers such as GCC.  Strictly speaking, CloseLibrary() expects an argument of type struct Library *.  The pointer IntuitionBase is of type struct IntuitionBase * not struct Library * (although the IntuitionBase structure actually begins with a Library structure) and therefore must be cast to a struct Library * when used in CloseLibrary().  Including the protos as mentioned earlier is a good way to catch these type mismatches.  By the way, which compiler are you using?

And yes, I forgot the return 0 at the end of main().  ;-)

Thank you for bringing up these errors.  I'll correct them and publish the updated tutorials.

Also, you might be able to find some very useful documentation near the bottom of  this (http://jove.prohosting.com/~peoyli/peo/computing/amiga/assembler/) page.
Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 10, 2003, 11:32:59 PM
Any particular reason to prefer AllocMem() / FreeMem() over AllocVec() and FreeVec()?

At least with the latter you can forget how big the allocation was and exec remembers for you.
Title: Re: "Close Window" tutorial errors
Post by: Sidewinder on May 11, 2003, 12:59:58 AM
@Karlos

No, there is no reason I prefer AllocMem() over AllocVec() other than AllocMem() is a more descriptive function name which helps new programmers understand what is actually happening.  It is also compatable accross all OSes if anyone is really still using OS 1.3.  :-D  But in practice, AllocVec() is prefered.
Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 11, 2003, 01:04:09 AM
That wasn't a criticism, btw :-)
I just figured AllocVec() / FreeVec() were more akin to malloc() and free() for those familiar with C but new to AmigaOS...
Title: Re: "Close Window" tutorial errors
Post by: Sidewinder on May 11, 2003, 01:33:28 AM
@Karlos

Hey, no problem.

You're exactly right, AllocVec() and FreeVec() are very much akin to ANSI C's malloc() and free().  The only difference is that AllocVec() allows you to specify different Amiga specific types of memory such as Chip RAM, Fast RAM, etc.

I'm certain I'll get into this more in one of my tutorials.  Right now I haven't even touched on memory management.   ;-)

Title: Re: "Close Window" tutorial errors
Post by: Thomas on May 11, 2003, 09:29:08 AM
Quote

You're exactly right, AllocVec() and FreeVec() are very much akin to ANSI C's malloc() and free(). The only difference is that AllocVec() allows you to specify different Amiga specific types of memory such as Chip RAM, Fast RAM, etc.


There is one additional major difference, mostly important for lazy (bad) programmers: malloc() does resource tracking. You can return from the program without explicitely calling free() and the startup code will return all allocated memory. Each AllocVec() *must* be matched by a FreeVec().

Bye,
Thomas
Title: Re: "Close Window" tutorial errors
Post by: cycloid on May 11, 2003, 02:02:58 PM
being a migrating winblows C++ coder i'd expect to use malloc (and thus having it auto-freed for me if i'm feeling lazy :) ) but i thought i'd better check first.

i'll get me a dev CD but of course that involves £££ and i have zero at the moment... anyone up for a swap of some kind? i've a spare 1200 :-)

Title: Re: "Close Window" tutorial errors
Post by: Sidewinder on May 11, 2003, 05:59:37 PM
@cycloid

[quote[
being a migrating winblows C++ coder i'd expect to use malloc (and thus having it auto-freed for me if i'm feeling lazy :) ) but i thought i'd better check first.
[/quote]

:-D  Heh, lazy programmers?  What is this you speak of?  ;-)  Honestly, resource tracking is cool, and malloc() works great for most things on the Amiga such as reserving space for structures, but if you are trying to reserve memory for things like graphics or sound you will need to use the AllocMem() or AllocVec() calls as they allow you explicitly specify that you want to reserve graphics (chip) memory.

Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 11, 2003, 06:03:58 PM
Quote

Sidewinder wrote:
Honestly, resource tracking is cool, and malloc() works great for most things on the Amiga such as reserving space for structures, but if you are trying to reserve memory for things like graphics or sound you will need to use the AllocMem() or AllocVec() calls as they allow you explicitly specify that you want to reserve graphics (chip) memory.



I have my own memory class for this (and other low-level memory related stuff) in C++ :-)
The class wraps AllocVec(), tracks allocations (safely freeing anything on exit) and supports features such as cache alignment and what not..

OOP rules :-)
Title: Re: "Close Window" tutorial errors
Post by: cycloid on May 12, 2003, 04:14:02 PM
i realised later that i'm doing things in C++ so actually just doing a "new" should do the allocing tracking for ya shouldnt it as a strcut is a class is an object in c++ innit! :-)


oh and the C++ thing goes for the (Library *) cast mentioned earlier. if IntuitionBase is a type of Library then any function that accepts a Library * will accept an IntuitionBase * by order of inheritance. of course if i want to do an IntuitionBase * thing in particular then the function would have to re-cast it back from a Library * ... i do lots of class based game type coding on the winblows box (e.g. a player is of type monster is of type animating is of type Entity)

C++ rules  :-D
Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 12, 2003, 06:51:52 PM
Well, that would be nice, but it's not exactly that way in AmigaOS.

AmigaOS was written in C, so the C++ style inheritance rules don't exactly apply.

However, the designers did go for the compositional approach, so the first member of struct IntuitionBase is struct Library (any extended library type has struct Library as it's first member).

This means that although not strictly correct from a purist point of view, the following works

struct IntuitionBase* IntuitionBase;

struct Library* p = (struct Library*)IntuitionBase;

This led to a small problem I found in Storm C++ where, due to the redundant 'struct' keyword, the compiler complained about the variable IntuitionBase ( a pointer to an IntuitionBase structure) having the same name as the object...
Easily fixed, but bizzare and unexpected :-)
Title: Re: "Close Window" tutorial errors
Post by: itix on May 12, 2003, 08:18:30 PM
Quote

Just add the GimmeZeroZero flag, then Intuition does that for you.


I wouldn't do that. GZZ window uses more RAM and slows down system.
Title: Re: "Close Window" tutorial errors
Post by: itix on May 12, 2003, 08:45:32 PM
Quote

There is one additional major difference, mostly important for lazy (bad) programmers: malloc() does resource tracking. You can return from the program without explicitely calling free() and the startup code will return all allocated memory. Each AllocVec() *must* be matched by a FreeVec().


Advanced programmer should prefer AllocPooled() call over AllocMem()/AllocVec() calls IMO. No more memory leaks (just remember DeletePool() on exit) and you also avoid memory fragmentation when doing small allocations.
Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 12, 2003, 09:26:28 PM
Quote

itix wrote:
Advanced programmer should prefer AllocPooled() call over AllocMem()/AllocVec() calls IMO. No more memory leaks (just remember DeletePool() on exit) and you also avoid memory fragmentation when doing small allocations.


Precisely why I program through an abstraction layer. Changing the internals of my Mem interface class is easy and doesn't break any of my application code (which also compiles under winblows, not that I'm maintainig it much just now)...
Title: Re: "Close Window" tutorial errors
Post by: cycloid on May 13, 2003, 02:32:24 PM
Quote

Changing the internals of my Mem interface class is easy and doesn't break any of my application code


now i'm curious, a bunch of #ifdefs? i'm targetting a mini-game for os4 along the lines of minesweeper (along those lines meaning, just a small game that gets really hard so you can play it instead of working) ... but of course if i'm beginning coding it in 3.1 then it might get released for that too :-) ...
Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 13, 2003, 03:07:51 PM
Hi Cycloid,

Nope, not conditional compilation as such. What I mean is I can just go in to my mem class and rewrite the internals. As long as I keep the same public interface to the class, nothing that uses it needs to change.

The public interface to the class is the same in the 68K, PPCWarpOS, linux and Win32 versions.

So changing the Amiga68K version's internal implementation from AllocVec() to allocVecPooled() or whatever may be an improvement but I don't have to worry about rifling through loads of application code and changing stuff.

For example, suppose my applications use Mem::alloc(), Mem::copy(), Mem::swap32() etc...example.
How class Mem works internally is not their concern, and nor should it be.
Its just your basic C++ encapsulation approach.

You can do the same thing in C too, just define a bunch of your own functions that are implementation dependent and then use them for everything else. Pretty standard really - thats all the ANSI C-library does anywayy ;-)

-edit-

Sorry I seem to have pulled this thread off topic


Title: Re: "Close Window" tutorial errors
Post by: cycloid on May 15, 2003, 01:05:17 PM
heh, i think i baited you off topic though.. but it looks like we're the only one's in here so that's ok :-)

that's pretty much what i suspected and i have a sudden urge to write a nice MM C++ class now. but i think i should get on with trying to load sprites and display them in my new window
Title: Re: "Close Window" tutorial errors
Post by: Karlos on May 15, 2003, 03:01:43 PM
Call me heretical but I like to hide away all the amiga stuff behind (portable) class interfaces. You won't even see so much as a ULONG in my application code... However, the fun is writing the amiga implementation, of course :-)

Nowadays, even my actual applications are classes. For example, here's the drawtest class definition that I used for the Warp3D thing...

  


class GfxTestApp : public AppBase, public Windowed {
  private:
    static char text[64];
    MilliClock timer;
    sint32 width;
    sint32 height;
    Rasterizer* gfx;
    DrawVertex* vertices;
    bool quit;
    bool flat;
    bool cull;
    bool zbuff;

    void genMesh(sint32 dx, sint32 dy);v
    void dumpPixelInfo(PixelDescriptor *pxl);
    void testMesh1();
    void testMesh2();

  protected:
    // Overridden from AppBase
    sint32 initApplication();
    sint32 runApplication();

    // Overriden from Windowed
    void keyPressNonPrintable(sint32 code);

  public:
    GfxTestApp();
    ~GfxTestApp();
};