The MShell Blog P2

The MShell Blog

(page 2)

The "Ultimate" OS-9/NitrOS-9 System GUI

Prev / Next

When Virtual Reality becomes Real Virtuality (12/26/2013)

I hope everyone had a Merry Christmas, personally, I'm waiting for a "Silent Night" (grandkids are here).

Well, I didn't make my Christmas debut for an MShell "demo" release, but I'm getting pretty close. I've decided to go through my current working code and do a major cleanup/renaming session. In using the old Ultimuse3 sources as a templet, a lot of the variable names and function names were just not suitable for my purposes. I have removed and commented out so much code that things were getting a little confusing. So, I'm basically going through each source and renaming everything to more recognizable naming conventions. I realized I needed to do this as I tried to work with the current set which included items referred to as "score", "note", and "staff". Arrays have to be reworked, constants redefined, and functions renamed. I've got about a weeks worth of changes before I can start working on making the virtual memory routines bend to my needs. This will take about a week as well. I had also run into a problem in implementing a series of special arrays to hold the various file types (PC, OS-9, and RSDOS), but after some discussion on arrays with Willard Goosey, I think we come up with a solution. Once the virtual memory buffers are in place, the OS-9 file manager is fairly easy to implement as most of it is already done. Thanks to the work I had already done in DW4Man, HRSView, and Sound Chaser, I have most of the file managers in a state that makes them easy to work into MShell. Once the file managers are in place, the foundation has been laid for most other subs/modules. All in all, I'm shooting for a demo by the end of Jan 2014, which was my original target for the demo release to start with.

I think some explination of my Color Computer/OS-9 "C" programming technique would help explain a lot of what I go through while programming in C on the Coco. I use what could be termed as "Multi-Source, Multi-Module, Fragged Sub" programming techniques. To be honest, I don't think I've ever done a "single source" C program in Coco OS-9. The very first C project I started was "Sound Chaser" which was loosely based from Mike Knudsen's "UBox3" sources which consisted of about 13 sources to create one OS-9 program module. I used these sources to "teach" myself C programming. Luckily, my choice of code to learn from was by one of the better C programmers for the Coco and OS-9. Mike has a degree in programming and retired from Bell Labs as a top C programmer. His C code for the Coco was by far more complex than any I have found in any of the C sources in the Coco archives and user group collections. The whole idea with multi-source code is to keep your code organized into catagories. Disk I/O, screen handling, math functions, keyboard/mouse input etc. The best example of such code I've seen is "Ultimuse 3" by Mike. The Umuse3 code uses almost every trick in OS-9 programming, then some that hadn't been thought of yet. A lot of programmers could have benifitted by researching this type of coding back in the 80s. I hope to soon release this code to the public soon in my "Coco Source Repository", then you can see for yourself. On my "MJK C Compiler System" page, I use Mike's "UBox3" sources as a "demo" program to explain the compiler system. UBox3 contains only a small portion of the complexity of Ultimuse3. I used UBox3 as my introduction to C and in that way was "wiened" on multi-source programming from the start. To really see how this works, just click the link in the left sidebar menu and download the entire disk set. The UBox3 sources are included in the tutorial. UBox3 is a fine example of how to keep your code clean and efficient.

Multi-Module code is a different moster. It's when you use different modules to make up one program enviroment. One of the first examples I saw of this kind of programming was in Tandy's "DeskMate". From one interface, you could run several modules and never leave the main interface. Then came Ultimuse3. Ultimuse3 in it's last incarnation on the Coco 3, consisted of a "main" module; "Umuse3", a forked and piped graphics driver; "Fran", and 9 "fragged" sub-modules; "Um3B", "Um3D", "Um3E", "Um3K", "Um3L", "Um3M", "Um3P", "Um3S", and "Um3T". I have since released a new new version of Ultimuse3 which includes 2 new fragged sub-modules; "Um3U" (Internet updater) and "Um3W" (DriveWire device manager). In creating these new modules, I had to learn how the "fragged" sub-modules system worked. This was a learning experience in itself. I will try to give a brief explination of how it works.

The idea is to have a sub-module that can be loaded into the main program's 64k workspace and accessed just as if it was part of the main sharing all functions and variables. First and foremost, there are memory/size limitations (of course). Here is a memory map of how Ultimuse3's memory is distributed:

Umuse3 (main w/STDOUT piped to Fran) - Program $9E00/Data $2000/System $200

this leaves $2000 for the GP buffer and $2000 for fragged Sub-Routines (below)

Fran (forked) - Program $7E00/Data $4000/Grf Work Area $4000/System $200

Um3B-W (fragged and linked by main) - Program $2000/Data 0 (shares the main's data space)

As long as one sticks to these limits, any number of modules can be created for Ultimuse3. Here is how it's done.

First, all direct page variable for the main and sub-modules must be in a seperate source file. This goes for all the global variables as well but in another source file. All these variables can be shared by the main and subs with a simple programming technique. Well, maybe not quite so simple...

Once the main has been compiled normally with the DP file, the global file is compiled to an asm file (xxx.a) and gets run through a program Mike created called "UnString". What this program does is to strip all the string initiaters from the global asm file, leaving only the pointers to them. The DP file has no "initiated" stuff in it so it is not stripped. Once this is done, you must decide what (if any) functions the main will be calling to the subs. Also what routines the subs will be calling from the mains. Each is handled differently. The main calls a sub by first linking in the sub, then passing up to 7 arguments to the sub. The first argument being a function code for what function in the sub you want to access (if there's more than one) and the rest being the data being passed. The sub is compiled with a special "cstart" written by Mike that does not "move" the variables and does a "JSR" into the sub instead of a "JMP". The main, while calling the sub, pushes it's PCR onto the stack which the sub will use for returning to that location on "return( )". It's actually not a s complex as it sounds once you see the small amount of code it takes to set it up. The sub is compiled with the new "stripped" globals which are really just pointers to the main's variables. Now to use any function in the main from the sub, you have to create what Mike calls "fcnptrs" or "function pointers". This consist of a list of any functions in the main that you plan to use from the subs. These functions are then defined to an alternate name to be used for the function. Here's and example:

This must be pre-declared somewhere in the main.

int Play( );

pplay = Play;

Now define it to be used in the globals

#ifdef INGLOBAL

#define PEXTERN

#else

#define PEXTERN extern

PEXTERN int (*pplay)

Now when the initial globals are compiled for the main, it will be defined as:

int (*pplay)

And once the globals for the subs are stripped and recompiled it will assume

extern int (*pplay)

This of course will just be a pointer to the actual function address. In this way, from the sub, if you want to call Play( ), you just use

(*pplay)( );

And the Play function will run and return back to the sub when it's done. Of course the function can pass arguments as well.

Mike also uses another set of custom modules to link in the subs. These are "NMLink" and "NMLoad". These commands are actually OS9 system calls and are called as such from Ultimuse3, but the stand alone cmds are very usefull for a lot of things. These programs will load and link modules into system memory (not the program's 64k workspace) without allocating any data storage space or extra memory. This meaning the program loaded or linked will only take up the amount of space it resides in and nothing more. Mike uses these routines to "NMLoad" a module before it is linked. In that way once he links it, it has 2 links in it's link map. Once you are done with the module and unlink it, it stays in memory until needed again. All the sub modules are treated this way and once they're loaded and linked the first time, they don't need to be loaded the 2nd time, just linked. This makes for faster linking times on subsequent calls to the modules. When the main finally exits, Mike makes sure the subs are all unloaded before exiting so that memory is returned to the system.

So in a nutshell... or should I say a Knudsenshell.. You have :

A special "cstart"

A string stripped shared global

Special arguments to call the sub

Pointers to the main's functions, callable by name.

That's about all I can think of without giving lengthy examples and a long winded explination. Maybe I will do a complete page on this one day. It's a very useful programming technique for OS-9.

*****************************************************************************************************************

Prev / Next

web counter