AMIGA alive

AMIGA alive
Showing posts with label software development. Show all posts
Showing posts with label software development. Show all posts

Friday, February 13, 2026

APTR is dead - long live APTR!

When browsing through AmigaOS developer documentation and C code, there's always a funny, interesting, sometimes enlightening little find.

It's just nice to see how it all ties together, and the changes made from one operating system (API) release to the next. Learning about the infrastructure of software, esp. over multiple versions, exposes some of the thinking process of the operating system developers. 

Sometimes, it also reveals long forgotten secrets. If you're a C coder using AmigaOS, chances are you've been using a datatype known as "APTR" somewhere in your code. It is used extensively throughout AmigaOS 1.3 Native Developer Kit (NDK) C include-files, and even more extensively throughout later NDK releases. 

And it turns out it's wrong!

From NDK 1.3 Includes exec/types.h:

typedef STRPTR      *APTR;      /* absolute memory pointer */

/* sigh.  APTR was misdefined, but compatibility rules.  Heres what it
 * should have been
 */
typedef ULONG       CPTR;       /* absolute memory pointer */

Yes, even the pros make a little mistake from time to time. Obviously, they kept compatibility, meaning they (and everybody else) kept using APTR, when it should be CPTR. 

Interestingly, in NDK 1.3 there is - a little - use of CPTR (in resources/filesysres.h, libraries/romboot_base.h, and libraries/expansion.h), but it has been half-removed (from libraries/romboot_base.h and libraries/expansion.h) and half-reintroduced (in dos/dosextens.h) with later NDK versions.

Chances are you've also been using datatypes SHORT and USHORT in your C code. Guess what: It's wrong, too! Here's another little snippet from NDK 1.3 exec/types.h that may clarify this further, long standing issue:

typedef short       WORD;       /* signed 16-bit quantity */
typedef unsigned short  UWORD;      /* unsigned 16-bit quantity */

...

/* For compatability only: (don't use in new code) */
typedef short       SHORT;      /* signed 16-bit quantity (WORD) */
typedef unsigned short  USHORT;     /* unsigned 16-bit quantity (UWORD) */

SHORT and USHORT are just backwards-compatable [sic] aliases for WORD and UWORD. 

Given the very non-volatile situation of AmigaOS development, both APTR and (U)SHORT won't give you a headache. APTR is used throughout the operating system, and will most likely never be replaced. CPTR is used only in less than a handful of cases - you'll probably never need it (and it has been moved to the "compatibility only" [sic] section of NDK 3.9 exec/types.h). (U)SHORT is deprecated since NDK 1.3, and hasn't been removed in later releases, so it's probably cemented into today's global AmigaOS code base, and will never be removed from the NDK.

So - lessons learned:

- use APTR, it's (not) correct

- (don't) use SHORT and USHORT

;-)

* * *

BONUS: 

Here's yet another nice, ancient compatibility [sic] snippet, from NDK 1.3 Includes libraries/dos.h, moved to dos/dos.h in NDK 3.9:

/* Relative position to Seek() */
#define OFFSET_BEGINNING    -1      /* relative to Begining Of File */

...

#define OFFSET_BEGINING     OFFSET_BEGINNING  /* ancient compatibility */

Thank you - one less typing error to worry about. :-)

Friday, November 8, 2024

A little odd: TAG_DONE and TAG_END

Sometimes one might get confused when to use TAG_DONE in AmigaOS C-code, and when to use TAG_END. The answer is very simple: They're one and the same. But it turns out there might be a little bit of an unknown story to these two widely used tokens.

TAG_DONE showed up before TAG_END, in NDK1.3, along with struct TagItem, but not as part of the system includes, and the TagItem system wasn't used in system functions.

Or was it? This is a section of code from the file Read-Me1.3/A2024Docs/OpenA2024.c, which is part of NDK1.3.

#define NONEWINCLUDES       1   /* don't have 1.3 includes yet  */

#if NONEWINCLUDES       /* Some additional definitions  */

/********** from intuition/screens.h ************/

#define NS_EXTENDED     0x1000  /* NewScreen.Extension is valid     */

struct TagItem
{
    ULONG   ti_Tag;     /* identifies the type of this item */
    ULONG   ti_Data;    /* type-specific data, can be a pointer */
};

/* ---- system tag values ----------------------------- */
#define TAG_DONE   (0L) /* terminates array of TagItems. ti_Data unused */
#define TAG_IGNORE (1L) /* ignore this item, not end of array       */
#define TAG_MORE   (2L) /* ti_Data is pointer to another array of TagItems
             * note that this tag terminates the current array
             */

Note the condition "#if NONEWINCLUDES". It looks as if these definitions were part of some "new includes" that weren't part of the distribution (yet?). 

There appears to be a nice little oddity here:

NS_EXTENDED (and TagItem) can't be found in intuition/screens.h, while other sections of the code (not shown here) can. The code contains a copy of NewScreen structure definition, only extended with an extra field, type TagItem pointer. It then creates an instance of that NewScreen structure, with type NS_EXTENDED, and calls OpenScreen() with that structure. There's no mentioning of NS_EXTENDED, or a TagItem pointer field in the Autodocs of OpenScreen() in this version of the NDK.

Does that mean that AmigaOS1.3 already had an (almost) undocumented feature, that would only be made (really) public with AmigaOS2?

TAG_END appears in NDK2.0, in new system include file utility/tagitem.h, as a clone of TAG_DONE, along with struct TagItem etc.:

NDK2.0-4/include/utility/tagitem.h

#define TAG_DONE   (0L) /* terminates array of TagItems. ti_Data unused */
#define TAG_END TAG_DONE

This NDK's version of intuition/screens.h also defines an ExtNewScreen structure that has the extra TagItem pointer field. 

Looking at the usage of TAG_DONE and TAG_END, across all files that are supplied with NDK2.0, there seems to be no preference. Maybe TAG_END was really just introduced to avoid interruptions in workflow, because many developers would intuitively think, and type, "end" instead of "done"?

Another tiny oddity is a change that appears in NDK3.1. It has a slightly different definition of TAG_END: It's still identical, but for some unexplainable reason, TAG_END isn't bound to TAG_DONE anymore. Instead, a comment explains why both use the same value.

Includes\&Libs/include_h/utility/tagitem.h

#define TAG_DONE (0L) /* terminates array of TagItems. ti_Data unused */
#define TAG_END (0L) /* synonym for TAG_DONE */

We'll probably never find out what happened, precisely.
But that's ok. Fortunately, TAG_DONE and TAG_END are either synonyms, or simply the same. ;-)



Tuesday, March 26, 2019

New facebook group for BlitzBasic/AmiBlitz coders

Yes, indeed, there used to be no facebook group specifically for Amiga BlitzBasic/AmiBlitz coders. This situation has just changed.



BlitzBasic, or AmiBlitz, is a BASIC dialect, originally developed specifically for the Amiga, keeping the Amiga hardware's special features in mind, allowing reasonably unexperienced coders to get great results, and quickly. Many games have been written in BlitzBasic, including the outstanding Lemmings-clone Blobz.

Surprisingly there wasn't a facebook group dedicated to Amiga BlitzBasic - until now. Amiga BlitzBasic coders now have a group on facebook to share, exchange, and chat about their BlitzBasic experiences.

The group's name is "Amiga BlitzBasic & AmiBlitz", it's a closed group, and as such of course you need to have a facebook account, and request to join the group.

C u there! Happy BlitzBasic coding!