Just in case you still want to do this, this version has a FlexProp C main interface and more separated Spin2 drivers.
Compiles with latest version of FlexProp C (4.5.0).
I'm curious as to how one can use Spin drivers with Catalina...
Would you run Spin2Cpp on it and then include assembly as binary blob?
This just shows a blue screen, but the mouse works.
Thanks, I'll have a look. The architecture of the Propeller, where most of the work is usually done in PASM in a separate cog, makes incorporating drivers into a high-level language fairly simple. In general, I just discard the Spin parts of a driver entirely (or rewrite them in C, which is usually fairly trivial) and instead use the PASM code pretty much "as is".
Ok thanks, that makes sense.
Pure c and assembly is probably superior for legibility and portability.
Not sure yet how important portability is in this particular instance, but still probably better as you suggest.
On the other hand it is nice when porting from spin2 to sorta cheat a bit and leave some parts in spin.
In this version, I've swapped out the palette for one with the 216 websafe colors, starting from black. Then, there's a few more shades of gray. Then, there are some extras that can be application specific.
Also, I think I've found a way to use structures to define the form data such as colors, elements, size and position, etc.
The attached now shows a blank form with title...
But, my C isn't so great and maybe there's a better way to do it.
The current way defines this stuff as global data. That seems to have some limitations.
My main hangup is how to make a list of objects for the form and have a pointer to that be part of the form structure.
This way uses this structure to do it:
This seems to work, but seems wasteful when the form does not have so many objects as MaxFormObjects in reality.
Had to do a similar thing for strings that define the text of an object like this:
char text[MaxFormText];
Maybe this is just a trivial amount of bytes and I shouldn't worry about it.
But, if somebody sees a better way, please let me know.
But, my C isn't so great and maybe there's a better way to do it.
The current way defines this stuff as global data. That seems to have some limitations.
My main hangup is how to make a list of objects for the form and have a pointer to that be part of the form structure.
This way uses this structure to do it:
This seems to work, but seems wasteful when the form does not have so many objects as MaxFormObjects in reality.
Had to do a similar thing for strings that define the text of an object like this:
char text[MaxFormText];
Maybe this is just a trivial amount of bytes and I shouldn't worry about it.
But, if somebody sees a better way, please let me know.
Well, in most cases, the FormObjectLists would be either defined at compile time or generated at runtime with a known limit, right?
So you could use arrays of variable size and use a null pointer to signal the end of the list.
Or you could store the FormObjects directly inside the list and have a special "end list" type.
You'd then pass around the pointer to such an array.
Another alternative is to have the FormObjects form (heh) a linked list, but those aren't nice to define as static data (in plain C, anyways. C++ is better at it).
Also, I am reminded of ye olde Allegro 4 GUI system. That one used/uses arrays of DIALOG structs that looked like this:
typedef struct DIALOG
{
int (*proc)(int, DIALOG *, int);
int x, y, w, h; /* position and size of the object */
int fg, bg; /* foreground and background colors */
int key; /* keyboard shortcut (ASCII code) */
int flags; /* flags about the object state */
int d1, d2; /* any data the object might require */
void *dp, *dp2, *dp3; /* pointers to more object data */
} DIALOG;
The interesting part is the proc function pointer. Aside from signalling end-of-list when NULL, it forms a basic event dispatching system - whenever anything needs to happen to an object, it gets called. The first parameter is the message type. This includes MSG_START/MSG_END when the object is created/destroyed, MSG_DRAW when the object needs redrawing, MSG_CLICK when it is clicked, etc. The DIALOG* is a pointer to the object in question and the meaning of the second int depends on the message (i.e. character codes for keyboard-related events). The function can then return a status code, such as D_REDRAWME/D_REDRAW to request redrawing this object/all objects, D_USED_CHAR if a typd character was consumed, etc.
This design made it really flexible and easy to extend with custom objects.
Thanks, that looks similar to what I'm doing.
Using 0 pointer to signify end of list.
The "void *dp" seems to be one way to do it, but I think the value has to be assigned inside a function, right?
For example, if I wanted to to point to a char array, seems I have to make the assignment inside a function, which I didn't want to do.
(or maybe I should try this again).
That first line "int (*proc)(int, DIALOG *, int);" is way over my head !
I've never used function pointers.
Seems that in C++ there are easier ways to do all this stuff...
The "void *dp" seems to be one way to do it, but I think the value has to be assigned inside a function, right?
For example, if I wanted to to point to a char array, seems I have to make the assignment inside a function, which I didn't want to do.
That first line "int (*proc)(int, DIALOG *, int);" is way over my head !
I've never used function pointers.
Seems that in C++ there are easier ways to do all this stuff...
The function pointer syntax is stupid. "int (*proc)(int, DIALOG *, int)" is a pointer named "proc" to a function like this
int something(int msg,DIALOG *this, int c) {
switch(msg) {
// Do stuff
}
}
// And it is then used as such
DIALOG my_diag[] = {
{
&something,
16,16,64,64,
// more data, you get the point
},
{NULL},
};
Comments
I modified the assembly to automatically update x and y values in the main code, whenever mous moves.
Thanks, I'll have a look. The architecture of the Propeller, where most of the work is usually done in PASM in a separate cog, makes incorporating drivers into a high-level language fairly simple. In general, I just discard the Spin parts of a driver entirely (or rewrite them in C, which is usually fairly trivial) and instead use the PASM code pretty much "as is".
Pure c and assembly is probably superior for legibility and portability.
Not sure yet how important portability is in this particular instance, but still probably better as you suggest.
On the other hand it is nice when porting from spin2 to sorta cheat a bit and leave some parts in spin.
Also, I think I've found a way to use structures to define the form data such as colors, elements, size and position, etc.
The attached now shows a blank form with title...
But, my C isn't so great and maybe there's a better way to do it.
The current way defines this stuff as global data. That seems to have some limitations.
My main hangup is how to make a list of objects for the form and have a pointer to that be part of the form structure.
This way uses this structure to do it:
This seems to work, but seems wasteful when the form does not have so many objects as MaxFormObjects in reality.
Had to do a similar thing for strings that define the text of an object like this:
Maybe this is just a trivial amount of bytes and I shouldn't worry about it.
But, if somebody sees a better way, please let me know.
Well, in most cases, the FormObjectLists would be either defined at compile time or generated at runtime with a known limit, right?
So you could use arrays of variable size and use a null pointer to signal the end of the list.
Or you could store the FormObjects directly inside the list and have a special "end list" type.
You'd then pass around the pointer to such an array.
Another alternative is to have the FormObjects form (heh) a linked list, but those aren't nice to define as static data (in plain C, anyways. C++ is better at it).
Also, I am reminded of ye olde Allegro 4 GUI system. That one used/uses arrays of DIALOG structs that looked like this:
The interesting part is the proc function pointer. Aside from signalling end-of-list when NULL, it forms a basic event dispatching system - whenever anything needs to happen to an object, it gets called. The first parameter is the message type. This includes MSG_START/MSG_END when the object is created/destroyed, MSG_DRAW when the object needs redrawing, MSG_CLICK when it is clicked, etc. The DIALOG* is a pointer to the object in question and the meaning of the second int depends on the message (i.e. character codes for keyboard-related events). The function can then return a status code, such as D_REDRAWME/D_REDRAW to request redrawing this object/all objects, D_USED_CHAR if a typd character was consumed, etc.
This design made it really flexible and easy to extend with custom objects.
Using 0 pointer to signify end of list.
The "void *dp" seems to be one way to do it, but I think the value has to be assigned inside a function, right?
For example, if I wanted to to point to a char array, seems I have to make the assignment inside a function, which I didn't want to do.
(or maybe I should try this again).
That first line "int (*proc)(int, DIALOG *, int);" is way over my head !
I've never used function pointers.
Seems that in C++ there are easier ways to do all this stuff...
Yeah, function pointers is a great idea, that's what I need to do (probably).
Of course you can assign pointers in static data. The above is perfectly valid C.
The function pointer syntax is stupid. "int (*proc)(int, DIALOG *, int)" is a pointer named "proc" to a function like this