Rainbow Check Plus

A followup from my previous post… This box, which appeared in Rainbow magazine, was called Rainbow Check Plus:

Rainbow Magazine checksums

It first appeared in the February 1984 issue, and was even featured on the cover:

The article “Rainbow Check Plus for the CoCo and MC-10” appears on page 21, and was written by H. Allen Curtis. (Why is that name so familiar?) I did not realize it was available for the MC-10 as well. Here is the listing for the CoCo version:

10 CLS:X=256*PEEK(35)+178
20 CLEAR25,X-1
30 X=256*PEEK(35)+178
40 FOR Z=X TOX+77
50 READ Y:W=W+Y:PRINT Z,Y;W
60 POKE Z,Y:NEXT
70 IFW=7985THEN80ELSEPRINT"DATA ERROR":STOP
80 EXEC X:END
90 DATA 182,1,106,167,140,60,134
100 DATA 126,183,1,106,190,1,107
110 DATA 175,140,50,48,140,4,191
120 DATA 1,107,57,129,10,38,38
130 DATA 52,22,79,158,25,230,129
140 DATA 39,12,171,128,171,128
150 DATA 230,132,38,250,48,1,32
160 DATA 240,183,2,222,48,140,14
170 DATA 159,166,166,132,28,254
180 DATA 189,173,198,53,22,126,0
190 DATA 0,135,255,134,40,55
200 DATA 51,52,41,0

But wait … there’s more. As I was looking into this, I learned that “Rainbow Check Plus” was a follow-up to “Rainbow Check” which appeared in January 1983. It seems the original “Rainbow Check” would not catch some key items:

  • Incorrect line numbers. “300 CLS” and “390 CLS” would provide the same check value.
  • Incorrect variables. It would not catch a wrong variable. The example given is that “F” would be the same as “E”.
  • Incorrect command words. SGN or SIN would provide the same checksum.

Now I really wonder what it was doing to generate the numbers, if it wasn’t looking at the actual line data ;-)

The original version appeared on page 95 as part of the “Assembly Corner” column by Dennis L. Lewandoski. The column was called “Let’s End Those Typing Errors Once and For All.” This version appeared in the form of an assembly language program listing, as well as a BASIC loader with DATA statements.

Here is the BASIC program listing for the original 1983 “Rainbow Check” version:

10 CLS:IFPEEK(116)=127 THEN X=32688 ELSE X=16304
20 CLEAR25,X-1
30 IFPEEK(116)=127 THENX=32688 ELSE X=16304
40 FORZ=X TO X+77
50 READY:W=W+Y:PRINTZ,Y;W
60 POKE Z,Y : NEXT
70 IFW=5718 THEN80 ELSE PRINT"DATA ERROR":STOP
80 EXEC X:END
90 DATA 182,1,106,167,141,0,68
100 DATA 134,126,183,1,106,190
110 DATA 1,107,175,141,0,57,48
120 DATA 141,0,4,191,1,107,57
130 DATA 129,10,38,44,52,22,220
140 DATA 27,147,25,142,4,0,141
150 DATA 6,31,152,141,2,32,25
160 DATA 52,2,68,68,68,68
170 DATA 141,4,53,2,132
180 DATA 15,129,9,46,4,139,112
190 DATA 32,2,139,55,167,128,57
200 DATA 53,22,126,0,0

Unfortunately, the assembly was not provided on Rainbow on Tape, so I would have to type it all in by hand.

I suspect I will have to do just that, as well as disassemble the 1984 version and see how both worked, which might explain the limitations of the original.

Until then…

Dragon User magazine and typing in assembly

Over on YouTube, user @ms-ex8em pointed me to the November 1988 issue of Dragon User magazine and a little program that helps you type in machine code program listings accurately.

I recall spending countless hours typing in machine code programs from Rainbow Magazine “back in the day”. These programs would be a few lines of BASIC followed by dozens or hundreds of lines of DATA statements with numbers that represented the bytes of the machine language program.

One such program I specifically remember was Zonx, a cool game with background sound effects. It appeared in the October 1985 issue. You can see what I typed in by checking out page 65. And page 67. And page 68. And page 70. And page 71.

https://colorcomputerarchive.com/repo/Documents/Magazines/Rainbow,%20The/The%20Rainbow%20Vol.%2006%20No.%2003%20-%20October%201986.pdf

And, somehow, I managed to type all of those numbers in and get a working program!

Rainbow did have one thing to help — and perhaps I used it. They had a small program you could run, then as you typed in your program listing, when you got to specific lines you could hit a key and it would spit out a number (a checksum?) and see if it matched their numbers:

Above, you can see what number should be expected when you got to line 150, 310, 440 and so on. After all the code was typed in, the final number it should give you was 238. This required you to type in the program exactly as it appeared including spaces and any other formatting.

It was not optimal, but it was better than nothing.

I also saw some BASIC loaders for machine language that took matters into their own hands, and had built-in checksum values in their DATA statements. For example, they would put a specific amount of numbers on each line, with a checksum of those numbers at the end. Say that amount of numbers was five. A line might look like this:

1500 DATA 1,1,1,1,1,5

In that silly example, you could add up ever five bytes you READ and then compare that to the 6th byte in each line. If it matched, continue. If it didn’t, the loader code would print some kind of message, hopefully indicating what line had a mismatch.

I always appreciated program listings that did that.

Now, back to @ms-ex8em… The code they shared was quite different. You can find it on page 12:

https://colorcomputerarchive.com/repo/Documents/Magazines/Dragon%20User/Dragon%20User%20-%208811%20-%20November%201988.pdf

I will do my best to type it in here, accurately.

10 REM HEX LOADER
20 CLEAR 200,31599
30 INPUT"START";ST
40 INPUT"END";ED
50 FOR J=ST to ED STEP 8
60 PRINT USING"##### : ";J;
70 INPUT A$
80 CS=0
90 FOR K=1 TO LEN(A$)
100 CS=CS+K*VAL("&H"+MID$(A$,K,1))
110 NEXT K
120 INPUT" = ";C
130 IF S<>CS THEN PRINT"CHECKSUM ERROR-TRY AGAIN":SOUND 1,1:GOTO 60
140 FOR K=0 TO 7
150 POKE J+K,VAL("&H"+MID$(K*2+1,2)
160 NEXT K,J

First comment… There appears to be a mistake in line 150. It should have two closing parens at the end of the line.

Now let’s see what this code is doing.

In line 10, the CLEAR reserves memory (so BASIC cannot use it) starting at 31599. This is because the machine language program will load starting at 31600.

In line 40, the user is asked to input the start and end of the program they will be typing in.

In line 50, there is a FOR/NEXT that goes from start to end, stepping by 8. This tells me they expect 8 bytes of data on each line the user types in. The first input should be at 31600, then the next at 31608 and so on.

The user types in the 16 characters (representing 8 hex bytes) shown in the box below. They look like this:

31600 : 8E7B6F9F74Be012B  = 1016

In line 80, a checksum is calculated by adding up the value of each character typed in that line.

In line 120, the user is asked to type in the checksum shown in the data listing.

In line 130, if the number the user typed in (from the data listing) does not match value the program calculated, an error message prints and it goes back to let the user retype the entire line.

If it matched, line 140 will then go through those 16 characters and create the byte value for each of the 8 data bytes and POKE them into memory at the proper place.

This repeats until the end address is reached. At that point, some new assembly language program has been loaded into memory starting at 31600.

Pretty cool!

The problem @ms-ex8em was seeing with this program was a ?TM ERROR. That is most likely showing up in line 150 because of the missing paren. Fix that, then maybe the rest will work ;-)

I thought this was a neat way to enter in machine code. What other neat ways did you see back then?

Comment away…

Need help linking Windows C to FTDI static libraries

UPDATE: A support person with FTDI reached out to me, and confirms their static library can only be used with Microsoft’s compiler. It will not work with GCC, etc. That is the root of my issue. My next question is going to be: Can I do C code with Visual Studio? More to come…


This should be a simple problem to solve, and this problem may be related to using the wrong compiler (a very old Clang 3.3).

FTDI provides device drivers for things like RS232 interfaces. FTDI drivers typically come with Windows, Linux and Mac. When writing a program to use the FTDI device, they provide header files, DLLs and .libs. These come in a .zip file:

FT4222HQ – FTDI

Inside this zip are two header files. One is for the common FTDI stuff (Open, Close, etc.). The second is for the FT4222 which is a USB-to-I2C chipset.

Both are provided as .libs for DLLs, or static libraries. They also provide 32-bit and 64-bit versions of each.

Header files:

\LibFT4222-v1.4.7\imports\ftd2xx
\LibFT4222-v1.4.7\imports\LibFT4222\inc

64-bit static libraries:

\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64
\LibFT4222-v1.4.7\imports\LibFT4222\lib\ucrt\amd64

The files I am using in my test project are:

LibTest.c
ftd2xx.h
LibFT4222.h
ftd2xx.lib (681 KB, 64-bit static library)
LibFT4222-64.lib (12,918 KB, 64-bit static library)

There are defines for each of the libraries that are supposed to be set before including the corresponding header file:

#define FTD2XX_STATIC
#define FT4222_STATIC

#ifndef FTD2XX_STATIC
#error FTD2XX_STATICmust be defined to use static libs.
#endif

#ifndef FT4222_STATIC
#error FT4222_STATIC must be defined to use static libs.
#endif

…though I would normally set it in my project settings.

This “should” be simple, but on LabWindows/CVI 2017 (which uses Clang 3.3), it has a two sets of linker errors to some Windows library stuff that I do not know how to resolve.

When I make a project in Code::Blocks which uses GCC, I only get one set of six mangled references.

GCC errors:

..\..\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64\ftd2xx.lib(x64\Release\FTD2XX.obj):(.text$mn+0xec)||undefined reference to `??3@YAXPEAX_K@Z'|
..\..\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64\ftd2xx.lib(x64\Release\FTD2XX.obj):(.text$mn+0x16d)||undefined reference to `??3@YAXPEAX_K@Z'|
..\..\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64\ftd2xx.lib(x64\Release\FTD2XX.obj):(.text$mn+0x1e5)||undefined reference to `??3@YAXPEAX_K@Z'|
..\..\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64\ftd2xx.lib(x64\Release\FTD2XX.obj):(.text$mn+0x25d)||undefined reference to `??3@YAXPEAX_K@Z'|
..\..\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64\ftd2xx.lib(x64\Release\FTD2XX.obj):(.text$mn+0x2d5)||undefined reference to `??3@YAXPEAX_K@Z'|
..\..\LibFT4222-v1.4.7\imports\ftd2xx\lib\amd64\ftd2xx.lib(x64\Release\fteepd.obj):(.data$r+0x0)||undefined reference to `??_7type_info@@6B@'|
||error: ld returned 1 exit status|
||=== Build failed: 7 error(s), 20 warning(s) (0 minute(s), 1 second(s)) ===|

Since GCC gets further, I am going to try to use it.

This sample project is just a test to link to Open and Close functions in the FTD2XX library. Nothing is being used in the FT4222 library, so it really is not part of this test, but ultimately I will need it.

My test program is:

#define FTD2XX_STATIC
#define FT4222_STATIC

// -lsetupapi -ladvapi32 -luser32

#ifndef FT4222_STATIC
#error FT4222_STATIC must be defined to use static libs.
#endif

#include <windows.h>

#include <stdio.h>
#include <stdlib.h>

#include "ftd2xx.h" // Add to include path.
#include "LibFT4222.h" // Add to include path.

int main (void)
{
FT_STATUS ftStatus = 0;
FT_HANDLE ftHandle;

ftStatus = FT_OpenEx ((void*)"PrecisePower A",
FT_OPEN_BY_DESCRIPTION,
&ftHandle);

if (FT_OK == ftStatus)
{
FT_Close (ftHandle);
}

return 0;
}

I am posting this to my blog in case someone else is searching for a solution for this.

Meanwhile, if you think you know how to get this to work, please let me know.

IMPORTANT INFO: The FTDI readme says it works in Visual Studio. They have one example they provide that does static linking and it builds just fine. I have not tested it to see if it actually works, and do not know how to tell if it truly is using the static libraries. (We have always used the DLL version of the libraries, and those work fine.)

Is is possible they made a library that will not work in Clang or GCC, but does work in Microsoft’s compiler?

Tips appreciate.

Recreating the Pac-Man maze in 1993

Many years ago, I played with drawing a 3-D maze under OS-9 on my Radio Shack CoCo 3. That demo is on the NitrOS-9 “Ease of Use” release under the name “semaze“. It lets you wander around a simple line maze:

There is even a map you can bring up with “?”:

As I mentioned years ago on this site, I had played with turning that into an OS-9 version of the classic Phantom Slayer 3-D game on the CoCo 1. I got as far as having my maze with a “phantom” in it that would wander around:

An unfinished CoCo 3 OS-9 3-D maze game inspired by the old “Phantom Slayer” by MED SYSTEMS.

But the oddest version was probably me putting the Pac-Man maze into my 3-D “engine” and then deciding to put dots around it, and make it refresh every half second or so, making it a “real time” game. With a prototype ghost (which appeared just as a large circle) wandering around!

And bringing up the map showed the Pac-Man maze:

In the days before the Internet, the only way I would have been able to recreate this map is if I had access to an accurate home port (I did not), or a picture in a magazine (maybe). I am guessing I based it on some CoCo Pac-Man clone with a fairly accurate maze.

How well did I do? Here is my CoCo version, then the actual arcade game, and the Arduino TV-Out version I was working on a decade ago (very accurate, down to the tiles).

I can see a few errors, like the bottom walls under the power pellets going into the maze an extra tile. And the dots are off. Today, I understand how the Pac-Man maze is laid out with tiles so it would be much easier to recreate my 3-D “DotMaze” game with an accurate map.

Maybe I will.

Old C dog, new C tricks part 2: i won’t use i

See Also: part 1, part 2, part 3, part 4 and part 5.

When I learned BASIC, manuals always showed the FOR/NEXT loop using the variable “I”:

FOR I=1 TO 100:NEXT I

“I” had no idea why this was, back then, but since then I have been told there was some history with some programming language that had certain letters reserved for certain features, such as as I for loops.

But is this true? A quick Google search produced an “AI summary”:

The convention of using “i” as the loop counter variable originates from the mathematical notation where “i,” “j,” and “k” are commonly used as indices or subscripts to represent integers in sequences or arrays. This practice was adopted early in computer science and has persisted due to its conciseness and familiarity among programmers. While any valid variable name could technically be used, “i” serves as a readily recognizable and easily understood placeholder for the loop index, especially in simple iterations. In nested loops, “j” and “k” are conventionally used for the inner loop counters.

– Google AI Summary of my search result.

But that’s not important right now…

I suppose I had a bit of O.C.D. in me, because starting with “I” seemed weird.

I would do my loops starting with “A”.

FOR A=1 TO 100:NEXT A

When variables needed to mean something, I’d use the one or two-character variable name that made sense — NM$ for Name string, UC for User Count, etc. But for loops and other things, I’d use A, B, C, D, etc.

C books were similar, showing “i” for loops:

for (int i=0; i<100; i++)
{
    ...stuff...
}

For some reason, I always used “i” in C rather than a, b, c… My nested loops looked just like the AI summary described:

for (int i=0; i<10; i++)
{
    for (int j=0; j<10; j++)
    {
        for (int k=0; k<10; k++)
        {
            ....stuff....
        }
    }
}

It was at a previous job that another embedded programmer said something to me that changed this forever.

“You can’t search for i…”

– paraphrased quote from embedded programmer I used to work with.

While today there are modern editors that let you specify how a search works — full word or partial, ignore case or case sensitive, and even regular expressions — but you can never depend on having access to those tools. Some jobs are very restrictive about the software you are allowed to install on your work computer. Some simply don’t allow any installs by employees: you get the set of preconfigured apps for the position (Microsoft Office for some roles, compilers and such for others, etc.) and that might be it.

He told me he used “idx” for loops, rather than “I”. And that was enough to change my C coding habits instantly. Even since, when I do a loop, it’s like this…

for (idx=0; idx<100; idx++)
{
    ...stuf...
}

And when I’m looping through things of a given type, it do things like:

for (int cardIdx=0; cardIdx<52; cardIdx++)
{
    ...stuf...
}

Who says you can’t teach an old dog new tricks?

What do you use for your loops? And why?

Comments, if you have them…

Color BASIC and octal

Updates:

  • 2025-02-19 – Thanks to a comment from William Astle, the term “decimal” number has replaced my incorrect use of “integer.” And per a comment from James Jones, a clarification that all values you input are still stored internally as the same type of numeric floating point – the parsing converts them all to this floating point representation.

Color BASIC had one type of number you could use: decimal. These are the normal numbers we use every day like 1, 50392 or 42.

A=42
PRINT "A IS";A

When Extended Color BASIC was added, the CoCo accepted the following notations for numeric constants: integer, hexadecimal and octal. (Internally, BASIC converts them all to the same numeric representation of a floating point value.)

Getting Started with Extended Color BASIC describes hex and octal as follows:

Extended Color BASIC lets you use both hexadecimal and octal constants.

Hexadecimal numbers are quantities represented in Base 16 notation, composed of the numerals 0 to 9 and the “numerals” A to F. Hexadecimal constants must be in the range 0 to FFFF, corresponding to the decimal range 0 to 65535.

To indicate that a number is an octal constant, precede it with the symbol &H, as shown here:

&HA010 &HFE &HDl &HC &H4000

Octal numbers are quantities represented in Base 8 notation, composed of the numerals 0 to 7. Octal constants must be in the range 0 to 177777. The computer stores them as two-byte integers that correspond to the decimal range 0 to 65535.

To indicate that a number is an octal constant, precede it with the symbol &0 or &, as shown here:

&070 &044 U1777 &7170 &17 &01234

The use of “hex” and octal constants is convenient in programs that reference memory locations and contents. For further information, read a book on machine-language programming.

– Getting Started With Extended Color BASIC (p. 195, 1984 revision)

I most likely learned hexadecimal when I was learning assembly language. Today, I use hex values often in C programming. But octal? I do not think I have ever used it for anything. Have you?

I do believe I have seen it used “in the real world.” In the late 1980s (possibly early 1990s) I had a Kawai K1 synthesizer keyboard. It organized its instrument settings (called “patches” in reference to early synthesizers using “patch cables” to route signals do different processors) into two groups of Internal (onboard storage, uppercase “I” and lowercase “I”) and two groups of External (memory card, uppercase “E” and lowercase “e”). Each section had eight patches.

My first commercial CoCo program was a MIDI Librarian that could read the patches from the synthesizer and save them to disk, or load patches from disk into the keyboard. The patch screen in question looked like this:

You will see that each area had four banks (A-D) and each of those had eight patches (1-8). Uppercase “I” was A(1-8), B(1-8), C(1-8) and D(1-8), and lowercase “i” was the same. This was also the same for the External banks.

Thus, octal. I could have used octal in my program — but I do not know if I even realized this was octal at the time. I’d have to think about how I would have even done that. Maybe something like this:

0 'OCTALIN.BAS (2-15-2025)
10 LINE INPUT "BANK (0-7):";B$
20 LINE INPUT "PATCH(0-7):";P$
30 NM=VAL("&O"+B$+P$)
40 PRINT "THAT IS PATCH #";NM

…though I do not recall how the MIDI messages. It could have just been a user interface thing and internally the patches were still 1-whatever.

But I digress.

Juan Castro posted to the Color Computer e-mail list about a bug in the octal routines:

Octal constant (Ex.: &O14 = 12 decimal)

It accepts 8 as a digit. D’oh. Try “PRINT &O18” in a CoCo 1 or CoCo 2.

Without having a CoCo3 at hand to check I’ll wager it patches that bug. All
it has to do is replace a LBHI with a LBHS.

Juan Castro
Enviado do meu Olivetti Programma 101
http://retropolis.com.br

Since an octal value should only be 0-7, a value of 8 is not valid octal.

10 CLS:PRINT"DEC","OCT"
20 FOR A=0 TO 10
30 PRINT A,VAL("&O"+STR$(A))
40 NEXT

This should print 0-7 then error out. Yet…

And is there really no better error than SYNTAX for this type of problem?

And naturally, I had to see what HEX values do. A valid hex digit is 0-9 and A-F, representing 0 to 15. Will it do a syntax error as well if I go past the letter F?

It appears it does not. It seems to bail on the parsing and print them as two variables. Which is a neat trick, since you have to put a space or semicolon between two variables if you want to print them otherwise.

To confirm that is what it is doing, I tried this:

Ah, so it is not treating this as variables “H” and “G”. And I just learned something new (and probably useless).

Something new (and probably useless)…

Integer values are things like 1, 2, or 152032. They are floating point values, so you can also have things like 1.2 or 33.5. Though, not always. Floating point values cannot represent every decimal value accurately, but that’s a story for another article…

Somewhere, someone learned that a decimal (period) by itself would be treated as zero. The fastest way to assign 0 to a variable in Color BASIC is like this:

A=.

Weird, but it works. It seems the parser starts looking for a fractional amount, like “.25” or whatever, so it processes the period and then there is nothing else so the code returns with 0 (the initialization value when the function is called). It is still weird, though.

I found out tonight that the same thing applies to hex. You can do this:

A=&H

…and you get a zero. Try “PRINT &H” to see for yourself.

Of course, I had to try a quick benchmark, sitting in a loop doing something like “Z=.” and another run doing “Z=&H”. 1000 times through with “Z=.” used 140 timer ticks. The “Z=&H” used 154. I guess that is the overhead of parsing two characters instead of one.

But I digress. Again.

I have not looked up what BASIC is doing (see the excellent “BASIC Unravelled” books for the disassembly of the BASIC ROMs), but I suspect the parser starts looking and finds the “&” followed by the “H” and is ready to parse… it then hits an invalid character, so the parsing is over and 0 is there. Then it sees the G, which is not a command so it is treated like a variable.

Using “PRINT” was deceiving. Had I just tried this:

A=&HG

…I would have got what I was expecting:

?SN ERROR

Thanks, Juan, for sharing this. I learned about a bug, and in writing this, discovered another odd thing, which is less odd now that I understand what happened.

Until next time…

Sub-Etha graphical adventures?

Around 93-94, I created a text adventure that featured black and white digitized pictures from the 1992 Atlanta CoCoFest. It was more of a “simulation” than a game — and even called itself a simulation on the splash screen. But, while browsing through the source code, I found there were quite a number of things you could “do” in the game, while the score let you know how much of it you completed.

I also found one from a Chicago CoCoFest, which seems to be complete other than missing the images. Rooms were numbers with the vendor name and description. It was kind of like “playing” one of my old CoCoFest reports. Trippy.

And a weird 3-D first-person Pac-Man game I was working on…

Now that I have Xroar running the current Ease of Use NitrOS-9 build, and have my CoCoSDC “real CoCo” hard drive image mounted as the second drive, I may finally be able to dig through all this stuff and see what else I have.

Like finding I made a Towel V1.05” — after I moved to Iowa! I have no recollection of that. Lots of stuff to get archived and posted online.

Should be fun.

Build a (marginally) better malloc and free

This is a dumb one, but maybe someone else will find it useful.

I have been working on some C code that uses dynamically allocated linked lists. There are index structures and record structures and individual elements of different kinds in the records, all malloc()’d and then (hopefully) free()’d at the end.

Since my background is low-resource embedded systems (one system has a mere 8K of RAM), I have never really done much with malloc(). In fact, on some of the environments I have worked in they did not even provide a malloc()/free(). And this is probably a good thing. Without an OS watching over you, any memory allocated that did not get properly freed (a “memory leak“) can be big trouble for an embedded system meant to “run forever without a reboot.”

What I am writing right now is for a PC, and my understanding is if you allocate a bunch of memory then exit, Windows will clean it up for you:

int main()
{
    char *ptr = malloc (65535); // Allocate 64K

    // And now just exit without freeing it.
    return 0;
}

But no one should be writing code like that intentionally. This is the same mentality that has people who throw their trash on the ground because “someone else will clean it up for me.” Just because you have a garbage collector doesn’t mean you should rely on it to clean up after your mistakes.

But I digress.

In my program, I was wondering if I was getting it right. Debug “printf” messages can only go so far in to seeing what is going on. Did I free every last record? Did all the elements inside the records get freed as well?

I have no idea.

MAUI to the rescue!

Then a memory popped into my head. When I worked for Microware Systems Corp., we had a New Media division that worked on digital TV set-top boxes. (Yes, Virginia, I saw a demo of streaming video-on-demand with pause, fast forward and rewind back in the summer of 1995. But that’s a story for another day…)

The D.A.V.I.D. product (Digital Audio Video Interactive Decoder) used various APIs to handle things like networking, MPEG video decoding, sound, and graphics. The graphics API was called M.A.U.I. (Multimedia Application User Interface).

MAUI had various APIs such as GFX (graphics device), DRW (drawing API), ANM (animation), CDB (configuration database?), BLT (a blitter) and more. There was even a MEM (memory) API that was a special way to allocate and free memory.

I did not understand much of this at the time, beyond the entry level stuff I sometimes taught in a training course.

But the memory API had some interesting features. The manual introduced it as follows:

“Efficient memory management is a requirement for any graphical environment. Graphical environments tend to be very dynamic when it comes to allocating and freeing memory segments. Therefore, unless an application takes specific steps to avoid it, memory fragmentation can become a serious problem.

The Shaded Memory API provides the facilities applications (and other APIs) required to manage multiple pools of memory.

– Microware MAUI manual, 2000

One interesting feature of this API was the ability to detect memory overflows and underflows. For example, if you allocate 50 bytes and get a pointer to that memory, then copy out 60 bytes, you have overflowed that memory by 10 bytes (“buffer overrun“). Likewise, if the pointer started at 0x1000 in memory, and you wrote to memory before that pointer, that would be a buffer underflow.

The manual describes it as follows:

To print the list of overflows/underflows call mem_list_overflows(). When a shade is created with the check overflows option true, safe areas are created at the beginning and the end of the segment. If these safe areas are overwritten, the overflow/underflow situation is reported by mem_list_overflows().

– Microware MAUI manual, 2000

This gave me an idea on how to verify I was allocating and freeing everything properly. I could make my own malloc() and free() wrapper that tracked how much memory was allocated and freed, and have a function that returned the current amount. Check it at startup and it should be zero. Check it after all the allocations and it should have some number. Free all the memory and it should be back at zero. (Malloc already tracks all of the internally, but C does not give us a legal way to get to that information.)

Simple!

Sounds simple!

At first, you might think it could be as simple as something like this:

static int S_memAllocated = 0;

void *MyMalloc (size_t size)
{
    S_memAllocated += size;

    return malloc (size);
}

Simple! But, when it comes time to free(), there is no way to tell how big that memory block is. All free() gets is a pointer.

Sounds almost simple!

To solve this problem, we can simply store the size of the memory allocated in the block of allocated memory. When it comes time to free, the size of that block will be contained in it.

To do this, if the user wanted to malloc(100) to get 100 bytes, you would allocate 100 + the size of an integer. You would then copy an integer containing the size of this allocated segment into the first bytes of the block (and increment the memory counter by that amount). After that, the pointer returned to the user should be after that copied integer. Like this:

malloc (100 + sizeof(int));
+---+----------------------+
|int| the user's 100 bytes |
+---+----------------------+
^
|_ return this location

When this memory is free()’d, the passed-in pointer would be adjusted back past the integer. Those bytes could be copied into an int (so you know how much to subtract from the counter) and then the block free()’d.

Sounds sorta simple?

Here is what I quickly came up with…

// MyMalloc.h
#ifndef MYMALLOC_H_INCLUDED
#define MYMALLOC_H_INCLUDED
size_t GetSizeAllocated (void);
void *MyMalloc (size_t size);
void MyFree (void *ptr);
#endif // MYMALLOC_H_INCLUDED

// MyMalloc.c
#include <stdlib.h> // for malloc()/free();
#include <string.h> // for memcpy()

#include "MyMalloc.h"

static size_t S_bytesAllocated = 0;

size_t GetSizeAllocated (void)
{
    return S_bytesAllocated;
}

void *MyMalloc (size_t size)
{
    // Allocate room for a "size_t" plus user's requested bytes.
    void *ptr = malloc (sizeof(size) + size);
    
    if (NULL != ptr)
    {
        // Add this amount.
        S_bytesAllocated = S_bytesAllocated + size;
        
        // Copy size into start of memory.
        memcpy (ptr, &size, sizeof (size));

        // Move pointer past the size.
        ptr = ((char*)ptr + sizeof (size));
    }

    return ptr;
}

void MyFree (void *ptr)
{
    if (NULL != ptr)
    {
        size_t size = 0;

        // Move pointer back to the size.
        ptr = ((char*)ptr - sizeof (size));
        
        // Copy out size.
        memcpy (&size, ptr, sizeof(size));

        // Subtract this amount.
        S_bytesAllocated = S_bytesAllocated - size;
        
        // Release the memory.
        free (ptr);
    }
}

Then, as a test, I wrote this program that randomly allocates ‘x’ blocks of memory of random sizes… then frees all those blocks.

#include <stdio.h>
#include <stdlib.h>

#include "MyMalloc.h"

#define NUM_ALLOCATIONS     100
#define LARGEST_ALLOCATION  1024

int main()
{
    char *ptr[NUM_ALLOCATIONS];
    
    printf ("Memory Allocated: %zu\n", GetSizeAllocated());

    // Allocate    
    for (int idx=0; idx<NUM_ALLOCATIONS; idx++)
    {
        ptr[idx] = MyMalloc ( rand() % LARGEST_ALLOCATION + 1);
        
    }

    printf ("Memory Allocated: %zu\n", GetSizeAllocated());

    // Free    
    for (int idx=0; idx<NUM_ALLOCATIONS; idx++)
    {
        MyFree (ptr[idx]);
    }

    printf ("Memory Allocated: %zu\n", GetSizeAllocated());

    return EXIT_SUCCESS;
}

When I run this, I see the memory count before the allocation, after the allocation, then after the free.

Memory Allocated: 0
Memory Allocated: 45464
Memory Allocated: 0

Since it is randomly choosing sizes, the number in the middle may* be different when you run it.

I then plugged this code into my program (I did a search/replace of malloc->MyMalloc and free->MyFree) and added the same memory prints at the start, after allocation, and after freeing.

And it worked. Whew! I guess I did not need to spend time writing MyMalloc() or this post after all.

But I had fun doing it.

Additional thoughts…

Thinking back to the MAUI memory API, extra code could be added to put a pattern at the start and end of the block. A function could be written to verify that the block still had those patterns intact, else it could report a buffer overflow or underflow.

Also, I chose “size_t” for this example just to match the parameter that malloc() takes. But, if you knew you would never be allocating more than 255 bytes at a time, you could change the value you store in the buffer to a uint8_t. Or if you knew 65535 bytes was your upper limit, use a uint16_t. This would prevent wasting 8 bytes (on a 64-bit compiler) at the start of each malloc’d buffer.

But why would you want to do that? If you were on a PC, you wouldn’t need to worry about a few extra bytes each allocation. And if you were on a memory constrained embedded system, you probably shouldn’t be doing dynamic memory allocations anyway! (But if you did, maybe uint8_t would be more than enough.)

I suppose there are plenty of enhanced memory allocation routines in existence that do really useful and fancy things. Feel free to share any suggestions in the comments.

Until next time…

Bonus Tip

If you want to integrate this code in your program without having to change all the “malloc” and “free” instances, try this:

// Other headers
#include "MyMalloc.h"
#define malloc MyMalloc
#define free MyFree

That will cause the C preprocessor to replace instances of “malloc” and “free” in your code to “MyMalloc” and “MyFree” and then it will compile referencing those functions instead.


* Or you may see the same number over and over again each time you run it. But that’s a story for another time…

Blog stats for January 2025

I am trying something new, when I remember to do it. Unfortunately, copying and pasting from the stats dashboard seems to make links that have no URL attached to them. Annoying. So for now, just the titles.

Top Posts & Pages:

  1. Using the DJI MIC 2 or Mic Mini with the iPhone native camera app
  2. DJI Neo error downloading videos to phone
  3. Splitting a 16-bit value to two 8-bit values in C
  4. Insta360 X3 and X4 file transfer comparisons
  5. Nested ternary operators in C
  6. Wire up your own RS-232 WiFi modem for under $10 using ESP8266 and Zimodem firmware.
  7. Wokwi online Arduino/ESP32 simulator
  8. C warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  9. Insta360 ONE X2 photo and video modes and filenames

I guess I need to post more CoCo articles and see if I can get those back in the Top 9.

Top Referrers:

  1. Reddit – mostly from posts in the Insta360 camera group, I believe.
  2. Facebook
  3. WordPress Android App
  4. ecosia.org – “The Greenest Search Engine on the Planet”
  5. vogons.org – a Hitchhiker’s Guide reference! Mostly about my WiFi modem experiments with the ZiModem firmware.
  6. youtube.com
  7. Hacker News
  8. ccsinfo.com – they sell the PIC24 compiler I use at work. I have this blog in my signature.
  9. cse2.chickenkiller.com

I was curious about #9:

chickenkiller.com is being shared via Free DNS, a dynamic DNS domain sharing project where members can setup, and administrate their dns entries on their own remote internet connected systems in real time.

– chickenkiller.com

Top Countries:

  1. United States
  2. Canada
  3. United Kingdom
  4. India
  5. Australia
  6. Germany
  7. New Zealand
  8. France
  9. China
  10. Russia

Old C dog, new C tricks part 1: NULL != ptr

See Also: part 1, part 2, part 3, part 4 and part 5.

Updates:

  • 2025-02-19 – “new information has come to light!”

As someone who learned C back in the late 1980s, I am constantly surprised by all the “new” things I learn about this language. Back then, it was a K&R-era compiler, so there were no prototypes, and functions looked like this:

main(argc,argv)
int argc;          /* argc = # of arguments on command line */
char *argv[];      /* argv[1-?] = argurments */
{
    ...stuf...
} 

…and this…

MallocError(wpath)
int wpath;
{
   ShutDown(wpath);
   fputs("\nFATAL ERROR:  Towel was unable to allocate necessary memory to process\n",stderr);
   fputs(  "              this directory.\n",stderr);
   sleep(0);
   exit(0);
}

Today’s article is not about how old I am, but about something I just started doing, and wish I had done long ago.

Yoda would be happy…

When I learned to program BASIC, I learned how to compare a variable:

IF A=42 THEN PRINT "DON'T PANIC!"

When I learned C, the thing I had to get used to was double equals “==” for compare and single equal “=” for assignment:

int a = 42;

if (a == 42)
{
    printf ("Don't Panic!\n");
}

This, of course, leads to a common mistake that I have stumbled on many, many times over the past decades: Sometimes a programmer misses one of those equals:

if (a = 42)
{
    printf ("Don't Panic!\n");
}

This will cause the code to always enter that section and run it, regardless of what you think “a” is set to. Why? Because it is basically saying “if a can be set to 42, then…”


Or does it?

Normally, I wait for a follow up to discuss corrections and additional details I learn from the comments, but this one deserves an immediate revision. Aidan Hall left this tidbit:

It’s even worse than what you suggest! Assignment expressions evaluate to the value that was assigned (on the RHS), so this if block wouldn’t run:

if (a = 0) {
puts(“zeroed”);
}

– Aidan Hall

I had mistakenly thought it was testing the result of “can a be assigned” and assuming this would always be true. I did not realize it was the value of the assignment that was used. Wowza. Thanks, Aidan! And now back to the original content…


By leaving out that second equal, it now becomes an assignment. It might as well be saying:

if (1)
{
    a = 42;
    printf ("Don't Panic!\n");
}

I have caught this type of thing in code I have worked on at several jobs. And, I’ve caught it in code I wrote as well. Even recently…

But Yoda would be proud. Smarter programmers already figured out that you can write those comparisons backwards, like this:

if (42 == a)
{
    printf ("Don't Panic!\n");
}

The first time I ever saw that was at a former job, and it was code from a team over in India. I thought this was very odd, and wondered if it was some odd convention in that country, similar to how in America we would write “$5” for five dollars, but in Europe it might be “5 €” for five Euros.

Honestly, as backwards as that looks to me, phonetically it makes more sense when you read it ;-)

And don’t get me started on America’s Month/Day/Year and how confusing OS-9’s “backwards” time of Year/Month/Day was… but I quickly adopted that, since you can sort dates that way, but not in the “normal” way.

But I digress…

By reversing these comparisons, you now eliminate the possibility of forgetting an equal. This won’t give an error (but a good compiler might give a warning):

if (a = 42)

…but this cannot be compiled:

if (42 = a)

When I started working on some new code this past weekend, I just decided to start doing things that way. It quickly becomes second nature:

if (NULL != ptr)
{
}

if (false == status)
{
}

But it still looks weird.

Now to fire up that old 1980s compiler and see if that was even possible back then…

Until next time…