Newton 2.x Q&A Category: Newton ToolKit

Copyright © 1997 Newton, Inc. All Rights Reserved. Newton, Newton Technology, Newton Works, the Newton, Inc. logo, the Newton Technology logo, the Light Bulb logo and MessagePad are trademarks of Newton, Inc. and may be registered in the U.S.A. and other countries. Windows is a registered trademark of Microsoft Corp. All other trademarks and company names are the intellectual property of their respective owners.


For the most recent version of the Q&As on the World Wide Web, check the URL: http://www.newton-inc.com/dev/techinfo/qa/qa.htm
If you've copied this file locally, click here to go to the main Newton Q&A page.
This document was exported on 7/23/97.

Newton ToolKit


NTK, Picture Slots and ROM PICTs (12/19/93)

Q: How can I use a PICT in ROM from a picture slot editor in NTK?

A: You must use an NTK AfterScript to set the appropriate slot in the view to point to the ROM based PICT (assuming that the constant for the PICT is defined in the NTK definitions file AND documented in the Newton Programmers Guide). Use something like this in the AfterScript:
thisView.icon := ROM_RouteDeleteIcon;


Recognition Problems with the Inspector Window Open (3/8/94)

Q: When I have the Inspector window open in NTK and I debug my application, recognition does not work properly and the Newton complains about lack of memory. However, when I disconnect the Inspector, recognition works fine. What is going on?

A: The NTK inspector window uses system memory on the Newton side; the Toolkit App itself makes use of MNP (a compression and error correction protocol) in the Newton, which uses a buffer shared with the recognition working memory.

Different releases of the Newton OS have different amounts of memory allocated for this shared area, so the problem may not be apparent on some units. However, if this happens you have several options:
• Disconnect the Inspector when testing the recognition side.
• Use the keyboard for text input while testing the code.
• Write shorter text items.


Accessing Views Between Layout Windows (6/7/94)

Q: I have problems setting a protoStaticText text slot that is in one linked layout window from a button that is in another linked layout window. I tried to allow access to the base view from both linked layouts, but this didn't help. I even tried to allow access from the base view to both layouts, but this didn't help, either. What should I do?

A: There is no way to declare views across the artifical boundary imposed by the linked layouts. Until this feature of NTK is implemented, you must either create the link yourself at run time, or declare the button to the top level of the linked layout, and then declare the link.

For example, consider a view called textThatChanges which a child of a view called changingContainer and is declared to changingContainer with the name textThatChanges. ChangingContainer is the base view for a layout which is linked into the main layout, and the link (in the main layout) is declared as changingContainerLink. Code in the main layout can change the text of the textThatChange view like so:
    SetValue(containerLink.whatToDo, 'text, "Turn and face the...")


To do the equivalent of the declare yourself:

1) In the viewSetupFormScript script of the 'buttonThatChanges button, set the value of the base view's slot 'theTextView to self, as in the following code fragment:
    func()
    begin
           base.theTextView := self;
    end

2) In the buttonClickScript script of the 'buttonThatSetsText button, use the global function SetValue to store new text in the text slot of the 'buttonThatChanges button, as in the following code fragment:

    func()
    begin
       SetValue(base.theTextView, 'text, "Now something happened!");
    end

Note that this example assumes the self-declared view called base. In your application, you may access your base view in a different way.


Dangers of StrCompare, StrEqual at Compile Time (6/9/94)

Q: I've noticed that StrCompare can return different results at compile time than it does at run time. What gives?

A: While most functions documented in the NewtonScript Reference are available at run time and at compile time (within the NTK environment), some functions have different behaviors.

In this case, the sort order for strings within the NTK NewtonScript environment is different from the ordering used on the Newton (and different from other commonly used desktop machine sort orders.) The differences are only apparent if you use characters outside the ASCII range, for instance, accented characters.

If it is necessary to pre-sort accented strings at compile time, you can write your own function that will return the same results as StrCompare on an given Newton unit. Here is one such function for English releases of the Newton OS (which assumes strings using only page 0 of the unicode table):

constant kNSortTable := '[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46, 47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68, 69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90, 91,92,93,94,95,96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, 81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106, 107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122, 123,124,125,126,127,128,129,130,131,132,133,161,157,135,136,165, 149,138,137,143,141,152,159,158,144,140,170,134,146,147,148,142, 150,138,168,171,151,153,160,153,154,155,156,174,174,174,174,65, 65,145,67,175,69,175,175,176,176,176,176,162,78,177,177,177,79, 79,164,79,178,178,178,85,166,167,139,65,65,65,65,65,65,145,67,69, 69,69,69,73,73,73,73,169,78,79,79,79,79,79,163,79,85,85,85,85,172, 173,89];

// function to compare strings (only page 0 characters)
// with the same order as the Newton ROM does.
DefConst('kNewtonStrCompare, func(s1, s2)
    begin
        local l1 := StrLen(s1);
        local l2 := StrLen(s2);
        local l := Min(l1, l2);
        local i := 0;
        while i < l and
            (r := kNSortTable[ord(s1[i])] - kNSortTable[ord(s2[i])]) = 0  do
                i := i + 1;
        if i = l then
            l1-l2
        else
            r;
    end); 

Note that just because you might find a particular function to be defined at compile time, do not assume that it behaves in exactly the same way as the like-named run-time function, unless the documentation explicitly says it does. (And, of course, it might not always be defined in the compile-time environment of future NTK products if it isn't documented that way.)


Profiler and Frames of Functions (7/10/95)

Q: Using the profiler with a large frame of functions gives confusing results. The profiler labels each function by the name of the frame and a number, but the numbers don't seem to correspond to the order in which I defined the functions. Moving the functions around doesn't change the profiler labels. How can I figure out which function is which?

A: If frames have less than than a certain number of slots (20 in the current release), the slots are kept in the order they were defined or added. If there are more than 20 slots in the frame, the slots are reordered. (This improves slot lookup operations.) The profiler in NTK 1.5 and NTK 1.6labels the functions by their position in the final, possibly reordered, frame.

To determine which function is in which position, you need to look at the frame after the reordering has occurred. You can do this by printing the frame after it's been defined. At compile time you can use a print statement in the slot editor or afterScript. After the package has been downloaded you can use the inspector. Then count (starting from one) through the slots to find your function.

Here's a little inspector snippet that will print the slots in a frame in order with their numbers:
    call func(theFrame) begin
        local i := 0;
        foreach slot, value in theFrame do begin
            print(i && ': && slot);
            i := i + 1;
        end
    end with (<the reordered frame>)



NTK 1.6 Heap/Partition Memory Issues (11/24/95)

Q: How do I set the build heap, main heap, and MacOS multifinder partition sizes in NTK 1.6 so I can build my package without running out of memory?

A: Here is an explanation of how Mac NTK makes uses of the various heaps. Understanding this will allow you to set your sizes for optimal performance. The same concepts apply to the Windows NTK, except for the sections talking about MacOS multifinder partitions.

Main Heap

The Main heap holds your frame data while you're working in NTK. Its size is set through the Toolkit Preference dialog. You must quit and restart NTK for changes to take effect.

The Main heap is allocated when NTK starts up. It is not disposed off until you quit NTK. If NTK can't allocate the Main heap it reports the problem and quits. As a result, if you can start NTK, Main heap allocation has completed.

We have no rule of thumb for setting the Main heap size. You need to experiment keeping the following in mind:

1) If the Main heap is insufficient, NTK will tell you so.
2) Reducing the Main heap size reduces overall RAM requirements.
3) The Main heap is garbage collected (GC). Increasing its size may improve performance by reducing GC activity. This will affect build time, and to a lesser degree the time it takes to open a project. Please note that the gains in build time are nonlinear and quickly reach a plateau, as shown in the following example:

            Main        Build time
    heap size        (+/- 0.5 sec)

        1250K            Main heap ran out of memory...
        1275K            32.7 sec
        1300K            26.4 sec
        1400K            22.3 sec
        1500K            19.2 sec
        1600K            17.5 sec
        2000K            16.0 sec
        3000K            15.2 sec


Experiment with Main heap size by measuring build time until you find a reasonable compromise between build time and memory requirements for your particular project.

If you are curious about GC activity, do the following:

1) Add the following line to your GlobalData file (in the NTK folder) and restart NTK:
    protoEditor:DefineKey({key: 65}, 'EvaluateSelection);

This allows you to use the period key on the numeric keypad to evaluate selected text in the Inspector window or any text file in the NTK build-time environment. (Normally the text is compiled by NTK and then evaluated by the Newton device when you hit the Enter key.) See the NTK User's Guide for details on the GlobalData file.

2) Type VerboseGC(TRUE) in the Inspector window, select, and hit the keypad-period key. Each time the GC kicks in, a line will be displayed in the Inspector window. By watching the frequency of GCs, you can get some idea of how your main heap is being used.

3) Use VerboseGC(FALSE) to turn this feature off. Please note that VerboseGC is available only in the NTK build-time environment. The function does not exist on the Newton device itself. It should be used only for debugging and optimization.

Build Heap

The Build heap holds your package frame data during the last part of the build. Its size is set through the Toolkit Preference dialog. Changes take effect immediately.

The Build heap is allocated only when the Build Package command is issued. It is released as soon as the resulting file is written to disk. As a result Build heap allocation is a recurring issue.

The rule of thumb is to set the Build heap to the size of your package (on the MacOS computer hard disk, not on the Newton device). If the Build heap is insufficient, NTK will tell you so.

There is nothing to be gained by setting the Build heap larger than necessary.

NTK first attempts to allocate the Build heap from MultiFinder memory. If that fails, NTK tries to allocate the Build heap from NTK's partition.

To verify that you have enough memory for the Build heap you need to look at the "About This Macintosh" dialog in the Finder application just prior to issuing the build command.

1) If the "Largest Unused Block" exceeds the Build heap requested size, the Build heap will be allocated from MultiFinder memory.

2) If 1 failed and NTK's partition bar shows enough free memory to accommodate the request, the Build heap will be allocated in NTK's partition.

3) If both 1 and 2 failed, the build will fail. Try to increase MultiFinder free memory by quitting any other open application, or increase the free memory in NTK's partition by closing some or all of NTK's open windows. Then try building again.

To prevent fragmentation of MultiFinder memory launch NTK first, and DocViewer, ResEdit, etc. afterwards. Whenever possible, quit those other applications in the reverse order .

Note: You can use Balloon help to see how much memory an application is actually using. Simply select the Show Balloons menu item and position the cursor on the application partition bar in the About Macintosh dialog. This feature is missing from PowerPC-based MacOS computers.

NTK Partition Size

For NTK 1.6 the rule of thumb for the "smallest useful" partition size for small projects is:
(3500K + Main heap size) for a 680x0 MacOS computer
(5500K + Main heap size) for a PowerPC MacOS computer with Virtual Memory off.

These rules do not include space for the Build heap.

The "smallest useful" partition size is defined by the following example: Using NTK default Main and Build heaps, open the Checkbook sample. Open one browser and one layout window for each file in the project, connect the Inspector, build and download. Perform a global search on "Check" (case insensitive) producing slightly more than 200 matches. Double click on several of these matches displayed in the search results window. Build and download again.

For serious work, increase the partition size by at least 256K for small projects, more for large ones. If you routinely perform global searches that produces many matches, see the next section.

On a PowerPC-based MacOS computer with Virtual Memory on, NTK's 2.7 Meg of code (the exact number is shown in the Finder Info dialog) stays on the hard disk, reducing memory requirements at the expense of performance.


NTK Search and Memory Hoarding (11/24/95)

Q: I sometimes run out space after working with a project for a while. How can I avoid this?

A: NTK 1.6 is built with the MacApp application framework, which brings with it certain memory requirements. Understanding the way NTK uses memory can help avoid running out of memory.

Most of user interface elements you see when using NTK are pointer-based MacApp objects. Allocating a large number of pointers in the application heap causes fragmentation. To prevent that, MacApp has its own private heap where it manages all these pointers.

This heap expands when necessary, but in the current implementation it never shrinks. This memory is not lost, but it may be wasted, effectively reducing free memory in the application partition.

During a single NTK session, build requirements are relatively constant. Partition size requirements will thus be mostly affected by the maximum number of NTK windows open at the same time. If you keep this number reasonable, relative to the partition size you can afford, there should be no problem.

The fact that MacApp's objects heap never shrinks can, however, become an issue when performing searches. The problem is not the search itself, but the number of matches. Each line you see in the Search Results window is a MacApp object occupying 500 to 800 bytes. If your search results in a large number of matches, you may run out of memory.

To reduce such occurrences:
1) Perform more focused searches to keep the number of matches per search reasonable.
2) Close the Search Results window as soon as you are done with it, preferably before doing another search.


NTK Stack Overflow During Compilation (11/24/95)

Q: When I build my project that has very deeply nested statements, NTK runs out of memory and quits. What's going wrong?

A: The deep nesting in your project is causing the compiler to overflow the stack space available in NTK. NTK 1.6 is more likely than than NTK 1.5 to suffer this problem due to new compiler code which nests deeper while parsing if-then-else statements, causing the stack to overflow into the application heap.

If you see an inadvertent crash in NTK during a save operation or a package build:

1) If you are familiar with MacsBug, examine the stack. This particular case will show up in the stack as several calls to the same function before the actual crash.
2) Otherwise, temporarily reduce the number of "else" branches and rebuild the package. If the problem disappears, stack overflow is the prime suspect.

There are at least three ways to avoid this problem and possibly improve performance at the same time:
1) Re-arrange the 'else' statements to resemble a balanced tree
2) Instead of If-then-else statements use:
An array of functions (with integers as selectors)
A frame of functions (with symbols as selectors)
3) Finally, as a temporary work around, you can increase the stack size using the ResEdit application.

Re-arrange the 'else' statements to resemble a balanced tree

This solution is the simplest to implement if you need to change existing code. It accommodates non-contiguous integer selectors, and in most cases is faster.

For example, the following code:
   if x = 1 then
        dosomething
    else
        if x = 2 then
            doSomethingElse
        else
            if x = 3 then
                doYetAnotherThing
            else
                if x = 4 then
                    doOneMoreThing
                else
                    if x = 5 then
                        doSomethingSimple
                    else
                        if x = 6 then
                            doThatThing
                        else
                            if x = 7 then
                                doThisThing
                            else // x = 8
                                doTheOtherThing

...can be rewritten like this:

   if x <= 4 then
        if x <= 2 then
            if x = 1 then
                doSomething
            else // x = 2
                doSomethingElse
        else
            if x = 3 then
                doYetAnotherThing
            else // x = 4
                doOneMoreThing
    else
        if x <= 6 then
            if x = 5 then
                doSomethingSimple
            else // x = 6
                doThatThing
        else
           if x = 7 then
                doThisThing
           else // x = 8
                doTheOtherThing;

Note that the if/then/else statement nesting is "unusual" to illustrate the nesting that the compiler must make each statement is nested as the compiler would process it.


Use an array of functions with integer selectors

Replace a long if-then-else statement with an array of functions. The code is more compact and readable. For a large set of alternatives, the faster direct lookup should compensate for the extra function call. This approach is most useful for a contiguous range of selector values (e.g., 11 to 65). It can accommodate a few "holes" (for example, 11 to 32, 34 to 56, 58 to 65). It is not practical for non-contiguous selectors (e.g., 31, 77, 256, 1038...)

For example, the following code:

    if x = 1 then
        dosuchandsuch;
    else
        if x = 2 then
            dosomethingelse;
        else
            if x = 3 then
                andsoon;

...can be rewritten like this:

        cmdArray := [func() dosuchandsuch,
        func() dosomethingelse,
            func() andsoon];

        call cmdArray[x] with ();


Use a frame of functions with symbols for selectors

This alternative provides the flexibility of using symbols for selecting the outcome.

For example, the following code:

    if x = 'foo then
        dosuchandsuch;
    else
        if x = 'bar then
            dosomethingelse;
        else
            if x = 'baz then
                andsoon;


...can be rewritten like this:
    cmdFrame := {foo: func() dosuchandsuch,
                    bar: func() dosomethingelse,
                    baz: func() andsoon};

      call cmdFrame.(x) with ();


Increase NTK's stack size using the ResEdit application

Open the Newton Toolkit application with ResEdit.

Double-click on the "mem!" resource icon

Double-click on resource ID 1000 named "Additional NTK Memory Requirements"

Change the fifth (and last) value. This is an hexadecimal number. In NTK 1.6, you should see "0001 8000" which is 98304 bytes (or 96k) to add to the total stack size. For example, to increase this value to 128k = 131072 bytes change the hexadecimal value to "0002 0000".


Unit Import/Export and Interpackage References (11/25/95)

Q: How can I reference information in one part or package from another (different) part or package?

A: Newton 2.0 OS provides the ability for packages to share informations by exporting or importing units. Units are similar to shared libraries in other systems.

A unit provides a collection of NS objects (unit members.) Units are identified by a name, major version number, and minor version number. Any frame part can export or import zero or more units.

A unit must be declared, using DeclareUnit, before it's used (imported or exported.) See the docs on DeclareUnit below for details.

To export a unit, call DefineUnit and specify the NS objects that are exported.

To import from a unit, simply reference its members using UnitReference (or UR for short.)


Unit Usage Notes

• Units can also be used to share objects among parts within a single package. This avoids the need to resort to global variables or similar undesirable techniques.

• A part can export multiple units. To achieve some degree of privacy, you can partition your objects into private and public units. Privacy is achieved by not providing the declaration for a unit.

• References to units are resolved dynamically whenever a package is activated or deactivated. For example, a package can be loaded before the package providing the units it imports is loaded. There will be no problem as long as the provider is loaded prior to actually using the imported members.

Conversely, it's possible for the provider to be deactived while its units are in use. The part frame methods, RemovalApproval and ImportDisabled, provide a way to deal with this situation.

Robust code should ensure that the units it imports are available before attempting to use their members. It should also gracefully handle the situation of units being removed while in use. See the DTS sample "MooUnit" for an example.

Unit Build-Time Functions

These functions are available in NTK at build-time only:

DeclareUnit(unitName, majorVersion, minorVersion, memberIndexes)

unitName - symbol - name of the unit
majorVersion - integer - major version number of the unit
minorVersion - integer - minor version number of the unit
memberIndexes - frame - unit member name/index pairs (slot/value)
return value - unspecified

A unit must be declared by DeclareUnit before it's used (imported or exported.) The declaration maps the member names to their indexes. A typical declaration looks like:

    DeclareUnit('|FastFourierTransforms:MathMagiks|, 1, 0, {
        ProtoGraph:     0,
        ProtoDataSet:   1,
    });


Typically, the declarations for a unit are provided in a file, such as "FastFourierTransforms.unit", that is added to an NTK project (similar to .h files in C.)

When resolving imports, the name and major version specified by the importer and exporter must match exactly. The minor version does not have to match exactly. If there are units differing only in minor version, the one with the largest minor version is used.

Typically, the first version of a unit will have major version 1 and minor version 0. As bug fixes releases are made, the minor version is incremented. If a major (incompatible) change is made, then the major version number is incremented.

Note: When a unit is modified, the indexes of the existing members must remain the same. In other words, adding new members is safe as long as the indexes of the existing members don't change. If you change a member's index it will be incompatible with any existing clients (until they're recompiled with the new declaration.)

DefineUnit(unitName, members)

unitName - symbol - name of the unit
members - frame - unit member name/value pairs (slot/value)
return value - unspecified

DefineUnit exports a unit and specifies the value of each member. Immediates and symbols are not allowed as member values. A typical definition looks like:

    DefineUnit('|FastFourierTransforms:MathMagiks|, {
    ProtoGraph:     GetLayout("foo.layout"),
    ProtoDataSet:   { ... },
});


A unit must be declared before it's defined. The declaration used when exporting a unit with n members must contain n slots with indexes 0..n-1. The definition must specify a value for every declared member (this is important.)

UnitReference(unitName, memberName)

or
UR(unitName, memberName)

unitName - symbol - name of a unit
memberName - symbol - name of a member of unit
return value - a reference to the specified member

To use a unit member call UnitReference (UR for short) with the unit and member name.

The unit name 'ROM can be used to refer to obects in the base ROM. For example:
UR('ROM, 'ProtoLabelInputLine).

Note: references to objects in the base ROM are sometimes called "magic pointers" and have traditionally been provided in NTK by constants like ProtoLabelInputLine or ROM_SystemSoupName.

In Newton 2.0 OS, there may also be packages in the ROM. These ROM packages may provide units. Their members are referenced just like any other unit, using UR, the unitName, and the memberName. This is the mechanism by which licensees can provide product-specific functionality.
AliasUnit(alias, unitName)

alias - symbol - alternate name for unit
unitName - symbol - name of a unit
return value - unspecified

AliasUnit provides a way to specify an alternate name for a unit. Since unit names must be unique, they tend to be long and cumbersome. For example:
    AliasUnit('FFT, '|FastFourierTransforms:MathMagiks|);


...so that you could write:
    local data := UR('FFT, 'ProtoDataSet):New(points);


...instead of:
    local data := UR('|FastFourierTransforms:MathMagiks|, 
    'ProtoDataSet):New(points);


AliasUnitSubset(alias, unitName, memberNames)

alias - symbol - alternate name for unit
unitName - symbol - name of a unit
memberNames - array of symbols - list of unit member names
return value - unspecified

AliasUnitSubset is similar to AliasUnit, except that it additionally specifies a subset of the units members which can be used. This helps restrict code to using only certain members of a unit.


Unit Part Frame Methods

These methods can optionally be defined in a part frame to handle units becoming unavailable.
RemovalApproval(unitName, majorVersion, minorVersion)

unitName - symbol - name of the unit
majorVersion - integer - major version number of the unit
minorVersion - integer - minor version number of the unit
return value - nil or string

This message is sent to a part frame when an imported unit is about to be deactivated. It may a return a string to be shown to the user as a warning about the consequences of deactivating the package in use. For example:

"This operation will cause your connection to fooWorld to be dropped."


Note: do not assume that the user is removing the package. Other operations such as moving a package between stores also cause package deactivation.

This message is only a warning. The user may decide to proceed and suffer the consequences. If the user proceeds, the ImportDisabled message (see below) will be sent.

If the removing the unit is not a problem (for example, your application is closed), then RemovalApproval can return nil and the user will not be bothered.

ImportDisabled(unitName, majorVersion, minorVersion)

unitName - symbol - name of the unit
majorVersion - integer - major version number of the unit
minorVersion - integer - minor version number of the unit
return value - unspecified

This message is sent to a part frame after an imported unit has been deactivated. The part should deal with the situation as gracefully as possible. For example, use alternative data or put up a Notify and/or close your application.

Unit-Related Glue Functions

These functions are available in the Newton 2.0 Platform file.

MissingImports(pkgRef)

return value - nil or an array of frames (see below)
glue name - kMissingImportsFunc

MissingImports lists the units used by the specified package that are not currently available. MissingImports returns either nil, indicating there are no missing units, or an an array of frames of the form:
    {
        name: symbol  - name of unit desired
        major: integer - major version number
        minor: integer - minor version number

        <other slots undocumented>
    }


Store parts and PowerPC-native NTK (5/15/96)

Q: When I build a store part with NTK 1.6 or 1.6.2 on my PowerPC MacOS computer, text searches (for example mySoup:Query({words: "pizza"}) don't sucessfully find the entries. Why?

A: On PowerPC MacOS computers only, there is a bug in 1.6 and 1.6.2 wherein building store parts will cause this behavior. The workaround is building the store part on a 680x0-based MacOS computer.

If you don't have a 680x0 machine available, you might try any of various third-party applications which remove the PowerPC-native code from an application which contains 680x0 code and PowerPC code, thus forcing it to run the 680x0 code instead. Before doing this, be sure to backup your copy of NTK!


CHANGED: Using Strings as Hex Data and Windows NTK (7/18/97)

Q: When I use SetClass(SetLength("\u<hex data>"), theLength), theClass) in Windows NTK , the binary object is not what I expect. It seems to be byte-swapped. How can I create binary objects with data in them in Windows NTK?

A: In Windows NTK (and other Windows NS environments), strings are stored in byte swapped order, that is, low byte first. This is because strings are basically arrays of 16-bit Unicode characters, and on the Intel platform 16-bit values are most usefully stored low byte first. Technically, changing the class and length of a string relies on the internal representation of strings, which isn't documented or supported, though it works fine on Newton OS and Mac OS platforms.

The correct way to create binary objects is to use the new MakeBinaryFromHex() function; it handles the byte-swapping issues properly. This function is defined by the platform file, and only runs at build-time -- it doesn't exist on the Newton device. You may need to get a newer platform file because this function was added after Windows NTK 1.6 shipped.