Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 11:48 08 Jan 2026 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MMbasic RP2350 V6.01.00EXP with user-defined structures

     Page 5 of 7    
Author Message
toml_12953
Guru

Joined: 13/02/2015
Location: United States
Posts: 540
Posted: 11:40am 01 Jan 2026
Copy link to clipboard 
Print this post

  matherp said  
Note: one user is reporting issues with XMODEM, can anyone confirm any problems? I can't replicate.


XMODEM RECEIVE

works fine but
XMODEM RECEIVE "structest.bas"

hangs up. The transfer never starts but Ctrl-C exits OK. I'm using EXP5 on a Pico2350DIL V1.2.
Edited 2026-01-01 21:44 by toml_12953
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10818
Posted: 12:04pm 01 Jan 2026
Copy link to clipboard 
Print this post

You don't say what you are using to transmit. Works perfectly for me EXP5 Pico2350DIL V1.2 with W11/Teraterm. Paste line delay set at 20mSec
 
toml_12953
Guru

Joined: 13/02/2015
Location: United States
Posts: 540
Posted: 12:45pm 01 Jan 2026
Copy link to clipboard 
Print this post

  matherp said  You don't say what you are using to transmit. Works perfectly for me EXP5 Pico2350DIL V1.2 with W11/Teraterm. Paste line delay set at 20mSec


I'm using Tera Term 5.40 on Windows 11. The box below never changes



Here are my options:
PicoMite MMBasic RP2350B V6.01.00EXP5
OPTION SERIAL CONSOLE COM2,GP4,GP5,BOTH
OPTION SYSTEM SPI GP10,GP11,GP12
OPTION SYSTEM I2C GP6,GP7, SLOW
OPTION FLASH SIZE 16777216
OPTION COLOURCODE ON
OPTION CONTINUATION LINES ON
OPTION CASE UPPER
OPTION DEFAULT COLOURS GREEN, BLACK
OPTION PICO OFF
OPTION CPUSPEED (KHz) 396000
OPTION LCDPANEL ST7796SP, PORTRAIT,GP14,GP15,GP13,,INVERT
OPTION SDCARD GP17, GP18, GP19, GP16
OPTION AUDIO GP26,GP27', ON PWM CHANNEL 5
OPTION PSRAM PIN GP0

Edited 2026-01-01 23:12 by toml_12953
 
bfwolf
Senior Member

Joined: 03/01/2025
Location: Germany
Posts: 131
Posted: 01:01pm 01 Jan 2026
Copy link to clipboard 
Print this post

  matherp said  V6.01.00EXP5

PicoMiteRP2040V6.01.00EXP5.zip

PicoMiteRP2350V6.01.00EXP5.zip

MMBasic_Structures_Manual.pdf

StructTest.zip

Removes STRUCT(SIZE as BOUND works
Adds STRUCT(OFFSET


You heard me...  

A heartfelt thank you from me!!!  I think the 'STRUCT(OFFSET' could really be very useful occasionally! Furthermore, there are now basically the same features for structs as in C...

  matherp said  In addition changes the syntax of all struct functions to match other MMbasic functions so:
STRUCT(SUBFUNCTION parameters) NOT STRUCT(SUBFUNCTION,parameters)
See manual for details


Good decision!!!

I could have easily lived with the previous syntax, but it's always better to be able to do similar things in the same way. You don't have to rethink things, and it prevents careless mistakes. Also, I suspect you like to use a generic function internally for evaluating subfunctions and their parameters anyway?

  matherp said  Assuming no further bugs reported or sensible and generally useful enhancements requested this will be the last experimental version before 6.02.00RC0


I just experimented a bit with 'ByRef' and 'ByVal' for struct arguments for functions and found a few minor issues and oddities:

Option Base 1
Option Explicit

Type TPerson
 phone As integer
 surname As string Length 8
 name As string Length 7
 padding As string Length 2 'alignment to uint32_t seems OK, L=6 for uint64_t
End Type

Dim people(2) As TPerson ' = (1234,"Marther","Peter", 5678,"Graham","Geoff")

people(1).phone = 1234
people(1).surname = "Marther"
people(1).name = "Peter"

people(2).phone = 5678
people(2).surname = "Graham"
people(2).name = "Geoff"

Dim i As integer
Dim o As integer

Print "SIZEOF(TPerson)="; Struct(SIZEOF "TPerson")
Print "OFFSET(TPerson,name)="; Struct(OFFSET "TPerson", "name")
o = Peek(VARADDR people(1).name) - Peek(VARADDR people(1))
Print "OFFSETOF(TPerson,name)="; o; " =0x"; Hex$(o)

Print "VARADDR(people(1))=0x"; Hex$(Peek(VARADDR people(1)))
Print "VARADDR(people(2))=0x"; Hex$(Peek(VARADDR people(2)))
Print "Bound(people(),1)="; Bound(people(),1)

Dim pt As TPerson

Dim p1 As TPerson
p1 = people(1)
Print "Struct Print p1:"
Struct Print p1

Print "At start:"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

people(1) = p1
TPerson.S9999(people(1))
Print "After TPerson.S9999(people(1))"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

people(1) = p1
TPerson.ByRef(people(1))
Print "After TPerson.ByRef(people(1))"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

people(1) = p1
Print "After people(1) = p1"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

' Same behavior as TPerson.Print(ByRef ..)
Print "TPerson.Print2(people(2)):"
TPerson.Print2(people(2))

people(1) = p1
' Throws error: "Error : Expected a structure variable: people(1)"
'TPerson.ByVal(people(1))
'Print "After TPerson.ByVal(people(1))"
'Print "TPerson.Print(people(1)):"
'TPerson.Print(people(1))

people(1) = p1
pt = people(1)
' Throws error: "Error : Expected a structure variable: pt"
'TPerson.ByVal(pt)

TPerson.S9999(pt)
Print "After TPerson.S9999(pt)"
Print "TPerson.Print(pt):"
' Throws error: "Error : Array dimensions" (inside Sub!, same at TPerson.Print2)
'TPerson.Print(pt)

End

Sub TPerson.Print(ByRef me As TPerson)
 ' Throws error: "Error : Array dimensions"
 'Struct Print me

 ' Prints whole array people():
 'Struct Print me()

 Local p As TPerson
 ' Throws error: "Error : Array dimensions"
 'p = me
 ''Struct Print p

 ' Works: !!!
 Struct Print me(1)  ' Prints the array-element passed by arg!
End Sub

' Without 'ByRef' but behaves the same as TPerson.Print(ByRef ..)
Sub TPerson.Print2(me As TPerson)
 ' Throws error: "Error : Array dimensions"
 'Struct Print me

 ' Prints whole array people():
 'Struct Print me()

 ' Works: !!!
 Struct Print me(1)  ' Prints the array-element passed by arg!
End Sub

Sub TPerson.S9999(me As TPerson)
 me.phone = 9999
End Sub

Sub TPerson.ByRef(ByRef me As TPerson)
 me.phone = 9999
End Sub

Sub TPerson.ByVal(ByVal me As TPerson)
 me.phone = 9999
End Sub



structs4.zip

Many Thanks and greetings!
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10818
Posted: 01:07pm 01 Jan 2026
Copy link to clipboard 
Print this post

Re the xmodem issue, what exact version of the firmware are you using USB? normal? What options?

  Quote  I just experimented a bit with 'ByRef' and 'ByVal' for struct arguments for functions and found a few minor issues and oddities:

Please explain what you are seeing in what cases rather than me having to disentanle your code. You cannot use byval with structs, you can't with arrays either.
Edited 2026-01-01 23:14 by matherp
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5592
Posted: 01:16pm 01 Jan 2026
Copy link to clipboard 
Print this post

  LeoNicolas said  This new data structure is super useful to organize complex data structures making the code more readable.

A real example from my Knightmare game, taking these global variables:


' Supports 13 shots at the same time: 0: id | 1: x | 2: y | 3: GPR 1 | 4: GPR 2 | 5: GPR 3
' The three first slots are for the player shots, the other ones for enemies
dim g_shots(12,5)
' Object data: 0: obj id | 1: x | 2: y | 3: life | 4: GPR 1 | 5: GPR 2 | 6: shadow
dim g_obj(20,6)


It is required to remember which position of the array stores the value I want to access. If I want to access an object X and Y position:

g_obj(0,1) and g_obj(0,2)

Now imagine that in the middle of hundreds of lines of code.

If a data type structure is much better. It will be something like this:

g_obj(0).X
g_obj(0).y
g_obj(0).life
Etc


I have yet to experience the benefit of structures, since I was not grown up in the object oriented age. After reading this thread, I hope to know more, but structures are (as I read on) not fully integrated in all other commands yet. I see Jim converting the structure to an array, just to plot the data. So there is room for improvement ahead...

In your typical case Leo, I wonder why you haven't defined constants, for use in the arrays. Makes life a lot easier.

CONST c_x=1
CONST c_y=2
CONST c_life=3

g_obj(0,c_x)
g_obj(0,c_y)
g_obj(0,c_life)
Etc...

Volhout
PicomiteVGA PETSCII ROBOTS
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10818
Posted: 02:07pm 01 Jan 2026
Copy link to clipboard 
Print this post

  Quote  I have yet to experience the benefit of structures, since I was not grown up in the object oriented age

Nothing to do with OO. Fully supported by COBOL, C, Pascal, Coral66(note the date), Algol68, Fortran90,  and even some versions of Basic (BBC Basic)
Edited 2026-01-02 00:09 by matherp
 
karlelch

Guru

Joined: 30/10/2014
Location: Germany
Posts: 310
Posted: 02:47pm 01 Jan 2026
Copy link to clipboard 
Print this post

  Volhout said  In your typical case Leo, I wonder why you haven't defined constants, for use in the arrays. Makes life a lot easier.

Constants for this purpose eat up valuable variable slots.
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5592
Posted: 02:59pm 01 Jan 2026
Copy link to clipboard 
Print this post

  karlelch said  
  Volhout said  In your typical case Leo, I wonder why you haven't defined constants, for use in the arrays. Makes life a lot easier.

Constants for this purpose eat up valuable variable slots.


Just learning, so I am curious if they don't require space when in structures ???
Somewhere the structure is defined, so somewhere the memory is reserved for the structure definition. Maybe that is more compact ?

Volhout
PicomiteVGA PETSCII ROBOTS
 
karlelch

Guru

Joined: 30/10/2014
Location: Germany
Posts: 310
Posted: 03:21pm 01 Jan 2026
Copy link to clipboard 
Print this post

  Quote  Somewhere the structure is defined, so somewhere the memory is reserved for the structure definition.

Interesting point.
Edited 2026-01-02 01:21 by karlelch
 
toml_12953
Guru

Joined: 13/02/2015
Location: United States
Posts: 540
Posted: 03:23pm 01 Jan 2026
Copy link to clipboard 
Print this post

  matherp said  Re the xmodem issue, what exact version of the firmware are you using USB? normal? What options?


I'm accessing the Pico2350DIL through the USB port. When I do an OPTION RESET, XMODEM "filename" works. When I use the options below, it doesn't. I've tracked it down to the SERIAL CONSOLE option. If I remove that option, XMODEM transfer works with a filename.

PicoMite MMBasic RP2350B V6.01.00EXP5
OPTION SERIAL CONSOLE COM2,GP4,GP5,BOTH
OPTION SYSTEM SPI GP10,GP11,GP12
OPTION SYSTEM I2C GP6,GP7, SLOW
OPTION FLASH SIZE 16777216
OPTION COLOURCODE ON
OPTION CONTINUATION LINES ON
OPTION CASE UPPER
OPTION DEFAULT COLOURS GREEN, BLACK
OPTION PICO OFF
OPTION CPUSPEED (KHz) 396000
OPTION LCDPANEL ST7796SP, PORTRAIT,GP14,GP15,GP13,,INVERT
OPTION SDCARD GP17, GP18, GP19, GP16
OPTION AUDIO GP26,GP27', ON PWM CHANNEL 5
OPTION PSRAM PIN GP0

Edited 2026-01-02 01:29 by toml_12953
 
bfwolf
Senior Member

Joined: 03/01/2025
Location: Germany
Posts: 131
Posted: 04:05pm 01 Jan 2026
Copy link to clipboard 
Print this post

  matherp said  
  Quote  I just experimented a bit with 'ByRef' and 'ByVal' for struct arguments for functions and found a few minor issues and oddities:

Please explain what you are seeing in what cases rather than me having to disentanle your code. You cannot use byval with structs, you can't with arrays either.


Okay, I suspected that `ByVal` wouldn't work with structs. It wouldn't be particularly good performance-wise and could also lead to memory or stack problems if the structs are very large or if arrays (of structs) are passed as arguments.
But being curious, I thought, "I'll try it and see what happens."

Perhaps it would then be useful to output an error message in the formal parameter list of the sub-definition if `ByVal` is used as a prefix before a struct type? That would also work for arrays.

I've now reduced my test program to a minimum and deleted everything related to `ByVal`.

There are still a few inconsistencies, though: I've commented out the commands that trigger the error with single quotes and added a comment explaining the error message and what unexpected happened. I hope that's clear enough? If necessary, activate the commented-out "sources of error".

Option Base 1
Option Explicit

Type TPerson
 phone As integer
 surname As string Length 8
 name As string Length 7
 padding As string Length 2 'alignment to uint32_t seems OK, L=6 for uint64_t
End Type

Dim people(2) As TPerson = (1234,"Marther","Peter","", 5678,"Graham","Geoff","")

Dim pt As TPerson

Dim p1 As TPerson
p1 = people(1)

Print "Struct Print p1:"
Struct Print p1 ' Works !

Print "At start:"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

' The "standard way"
people(1) = p1
TPerson.S9999(people(1))
Print "After TPerson.S9999(people(1))"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

' Same function but with "ByRef" and behaves like TPerson.S9999() as expected..
people(1) = p1
TPerson.ByRef(people(1))
Print "After TPerson.ByRef(people(1))"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))

' Value of people(1) should be "restored" - OK!
people(1) = p1
Print "After people(1) = p1"
Print "TPerson.Print(people(1)):"
TPerson.Print(people(1))
Print "TPerson.Print(people(2)):"
TPerson.Print(people(2))

' Pass e single struct var to TPerson.S9999(pt) - OK!
pt = people(1)
TPerson.S9999(pt)
'Print "After TPerson.S9999(pt)"
'Print "TPerson.Print(pt):"

'Bug! Throws error: "Error : Array dimensions" (inside Sub!)
'TPerson.Print(pt)

End

Sub TPerson.Print(me As TPerson)
 Print : Print "In Sub TPerson.Print(me As TPerson), Print me.name:"
 Print me.name

 'Bug! Throws error: "Error : Array dimensions"
 'Struct Print me

 'Bug! Prints whole array people(), while 'me' is no array !!!
 'Struct Print me()

 Local p As TPerson

 'Bug! Throws error: "Error : Array dimensions"
 'p = me

 'Struct Print p ' Should work, but irrelevant cos bug before..

 ' Works, but "weird", as 'me' is no array !!!
 Print : Print "In Sub TPerson.Print(me As TPerson), Struct Print me(1):"
 Struct Print me(1)  ' Prints the array-element passed by arg!
End Sub

Sub TPerson.S9999(me As TPerson)
 me.phone = 9999
End Sub

Sub TPerson.ByRef(ByRef me As TPerson)
 me.phone = 9999
End Sub



structs5.zip

Regards.

P.S.: You and others may have already noticed the subnames I chose — for example, 'Sub TPerson.Print(me As TPerson)' — it's great that MMBasic allows a '.' in subnames! This way, you can prefix the struct type the sub should work on in the subname.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10818
Posted: 04:06pm 01 Jan 2026
Copy link to clipboard 
Print this post

Of course, It works with USB-CDC or a serial console but if you enable both it is bound to get confused because both will be waiting for the ack and only one will get it
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10818
Posted: 04:18pm 01 Jan 2026
Copy link to clipboard 
Print this post

Sorry but your program is too confusing for me to understand. This is the output I get. Please describe what is wrong
truct Print p1:
TPERSON:
 .PHONE = 1234
 .SURNAME = "Marther"
 .NAME = "Peter"
 .PADDING = ""
At start:
TPerson.Print(people(1)):

In Sub TPerson.Print(me As TPerson), Print me.name:
Peter

In Sub TPerson.Print(me As TPerson), Struct Print me(1):
TPERSON:
 .PHONE = 1234
 .SURNAME = "Marther"
 .NAME = "Peter"
 .PADDING = ""
After TPerson.S9999(people(1))
TPerson.Print(people(1)):

In Sub TPerson.Print(me As TPerson), Print me.name:
Peter

In Sub TPerson.Print(me As TPerson), Struct Print me(1):
TPERSON:
 .PHONE = 9999
 .SURNAME = "Marther"
 .NAME = "Peter"
 .PADDING = ""
After TPerson.ByRef(people(1))
TPerson.Print(people(1)):

In Sub TPerson.Print(me As TPerson), Print me.name:
Peter

In Sub TPerson.Print(me As TPerson), Struct Print me(1):
TPERSON:
 .PHONE = 9999
 .SURNAME = "Marther"
 .NAME = "Peter"
 .PADDING = ""
After people(1) = p1
TPerson.Print(people(1)):

In Sub TPerson.Print(me As TPerson), Print me.name:
Peter

In Sub TPerson.Print(me As TPerson), Struct Print me(1):
TPERSON:
 .PHONE = 1234
 .SURNAME = "Marther"
 .NAME = "Peter"
 .PADDING = ""
TPerson.Print(people(2)):

In Sub TPerson.Print(me As TPerson), Print me.name:
Geoff

In Sub TPerson.Print(me As TPerson), Struct Print me(1):
TPERSON:
 .PHONE = 5678
 .SURNAME = "Graham"
 .NAME = "Geoff"
 .PADDING = ""
 
bfwolf
Senior Member

Joined: 03/01/2025
Location: Germany
Posts: 131
Posted: 04:44pm 01 Jan 2026
Copy link to clipboard 
Print this post

  matherp said  Sorry but your program is too confusing for me to understand. This is the output I get. Please describe what is wrong


Sorry - I did my best..
I deactivated the "offending" commands by prepending ' so that the code is "runable" I did this to isolate the bugs/issues "step-by-step". What you see with the "unmodified" code is OK..

Look at lines 54, 63, 66, and 71 - and remove the ' in front and see, what happens..

And in line 77: The code runs with 'Struct Print me(1)' though the variable 'me' (parameter of Sub TPerson.Print) is no array!

But instead it fails as 'Struct Print me' like deaktivated in line 63  

Perhaps this is something within 'Struct Print' ?
This could also be the source of the problem with line 54 ?
 
bfwolf
Senior Member

Joined: 03/01/2025
Location: Germany
Posts: 131
Posted: 04:50pm 01 Jan 2026
Copy link to clipboard 
Print this post

  Volhout said  
  karlelch said  
  Volhout said  In your typical case Leo, I wonder why you haven't defined constants, for use in the arrays. Makes life a lot easier.

Constants for this purpose eat up valuable variable slots.


Just learning, so I am curious if they don't require space when in structures ???
Somewhere the structure is defined, so somewhere the memory is reserved for the structure definition. Maybe that is more compact ?

Volhout


In the Struct-Manual:
Limitations
- Maximum structure types: 32
- Maximum members per structure: 16

And Peter said, the Structs are allocated on the heap so the don't eat up RAM if you don't use them. In the end, they need RAM, of course.

BUT: I suppose a single Struct-Type-variable counts as 1 variable in the var-table while storing several values that would be in several variables without structs..

bfwolf
Edited 2026-01-02 02:52 by bfwolf
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10818
Posted: 05:07pm 01 Jan 2026
Copy link to clipboard 
Print this post

What version are you testing on? Let me know and I'll post fixes until sorted.
 
bfwolf
Senior Member

Joined: 03/01/2025
Location: Germany
Posts: 131
Posted: 05:18pm 01 Jan 2026
Copy link to clipboard 
Print this post

  Mixtel90 said  @bfwolf
Yay!!! I *love* "Dinner for One" and have seen it many times. :)  No, it's not as popular here as it is in Germany where, I believe, it's close to being required viewing every year!

Happy New Year everyone. :)


Yes, indeed: "Dinner for One" is a must-see on TV in Germany on New Year's Eve!

Yes, i know, it's "off-topic", but I don't want to deprive everyone who understands English of these 30 minutes of "stomach hurting from laughing"...
https://www.youtube.com/watch?v=5n7VI0rC8ZA

There's another old comedy series from the 70s called "Ein Herz und eine Seele" (One Heart and One Soul), which also has a "New Year's Eve edition" that's broadcast every year: "Der Silvester-Punsch" (The New Year's Punch). Caution: 47 minutes!

https://www.youtube.com/watch?v=Z3056YZ6ZxM

The main character, "Alfred Tetzlaff," can be described, to put it kindly, as "very, very, very conservative"... Or better yet, as a socialist-hater... And he's constantly ranting about the SPD (Social Democratic Party), which governed Germany in the early 70s and provided the Chancellor, Willy Brandt. And he's always arguing with his son-in-law, who's an SPD supporter, and he harasses his wife, "Else"...

Have much fun!
 
toml_12953
Guru

Joined: 13/02/2015
Location: United States
Posts: 540
Posted: 05:24pm 01 Jan 2026
Copy link to clipboard 
Print this post

  bfwolf said  
There's another old comedy series from the 70s called "Ein Herz und eine Seele" (One Heart and One Soul), which also has a "New Year's Eve edition" that's broadcast every year: "Der Silvester-Punsch" (The New Year's Punch). Caution: 47 minutes!

https://www.youtube.com/watch?v=Z3056YZ6ZxM

The main character, "Alfred Tetzlaff," can be described, to put it kindly, as "very, very, very conservative"... Or better yet, as a socialist-hater... And he's constantly ranting about the SPD (Social Democratic Party), which governed Germany in the early 70s and provided the Chancellor, Willy Brandt. And he's always arguing with his son-in-law, who's an SPD supporter, and he harasses his wife, "Else"...

Have much fun!


It sounds sort of like an American favorite, All in the Family. The story of Archie Bunker, ultra-conservative who's rather mean to his son-in-law, Mike whom he calls meathead and wife, Edith.
Edited 2026-01-02 03:26 by toml_12953
 
bfwolf
Senior Member

Joined: 03/01/2025
Location: Germany
Posts: 131
Posted: 05:49pm 01 Jan 2026
Copy link to clipboard 
Print this post

Oh - almost missed it amidst all the "New Year's Eve fun"...

  matherp said  What version are you testing on? Let me know and I'll post fixes until sorted.


PicoMite MMBasic RP2350B V6.01.00EXP5
Copyright 2011-2025 Geoff Graham
Copyright 2016-2025 Peter Mather

Total of 6 Mbytes PSRAM available
> option list
PicoMite MMBasic RP2350B V6.01.00EXP5
OPTION FLASH SIZE 16777216
OPTION COLOURCODE ON
OPTION PICO OFF
OPTION CPUSPEED (KHz) 200000
OPTION PSRAM PIN GP47
>

Hardware is a Pimoroni Pico Plus 2
And i use Teraterm 4.106 on Win11 - nearly always..

Hope, it helps?

Ah – and almost forgot:
An observation I've made several times... In the editor, when "Mark Mode" is active, the cursor gets stuck on the bottom line, even when you press "Cursor Down". So the editor doesn't scroll. Is this intentional? Sure – one can live with it.
Edited 2026-01-02 03:54 by bfwolf
 
     Page 5 of 7    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2026