6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri May 10, 2024 9:38 pm

All times are UTC




Post new topic Reply to topic  [ 338 posts ]  Go to page Previous  1, 2, 3, 4, 5 ... 23  Next
Author Message
PostPosted: Mon Dec 10, 2018 9:11 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
BigDumbDinosaur wrote:
If you are not using the BASIC interpreter you can take up all zero page from $02 to $8F inclusive without interference.

I'm not using the BASIC interpreter. Fleet Forth's cold start routine switches out the BASIC ROM and replaces BASIC's routine at $300 with its warm start routine.
Thank you for the info on zero page but I was already aware of it. Fleet Forth uses most of that range for its data stack, some for the scratch pad area N, and some for some of the Forth virtual machine registers. Since Fleet Forth supports multitasking ( background tasks anyway ) the area of zero page used for the data stack gets divided among the foreground task and the background tasks. The reason I'm reluctant to put NEXT in zero page is that it is a routine that is around two dozen bytes long.
Quote:
Upon exit from the Forth kernel you will have to jump to the BASIC cold start entry point at $A000 to initialize BASIC's ZP.

Fleet Forth has a word BYE that returns to basic by way of the processor's system reset hardware vector at $FFFC.


Top
 Profile  
Reply with quote  
PostPosted: Fri Jan 04, 2019 12:06 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
I've just rewritten the code for : (colon) and ; (semicolon) in the Fleet Forth kernel.
SMUDGE , CSP , and ?CSP have been removed. There is a new word, TSB ( toggle smudge bit ) which takes an address and toggles the 5th bit ( value $20 ).
the old versions were.
Code:
: ;  ( -- )
   ?CSP  COMPILE EXIT
   SMUDGE [COMPILE] [ ; IMMEDIATE

: :  ( -- )
   ] SP@ CSP !
   CURRENT @  CONTEXT !
   CREATE  SMUDGE
   ;CODE
   IP 1+ LDA,  PHA,
   IP    LDA,  PHA,
   CLC,
   2 # LDA,  W    ADC,  IP    STA,
       TYA,  W 1+ ADC,  IP 1+ STA,
   NEXT JMP,  END-CODE

The new versions are as follows.
Code:
: ;  ( ADR TRUE -- )
   COMPILE EXIT
   [COMPILE] [
   TRUE ?PAIRS  TSB ; IMMEDIATE

: :  ( -- ADR TRUE )
   CURRENT @  CONTEXT !
   CREATE  LATEST TRUE OVER TSB ]
   ;CODE
   IP 1+ LDA,  PHA,
   IP    LDA,  PHA,
   CLC,
   2 # LDA,  W    ADC,  IP    STA,
       TYA,  W 1+ ADC,  IP 1+ STA,
   NEXT JMP,  END-CODE

?PAIRS takes two numbers and aborts with the message "STRUCTURE MISMATCH" if they are not the same.
This modification also made it necessary to change DOES> , ;CODE , CODE , and END-CODE .
I feel this is more in keeping with the Forth-83 standard.
Code:
:            -- sys                        M,79          "colon"

...  sys is balanced with its corresponding ; .
See: "compilation"  "9.4 Compilation"

And
Code:
 ;            --                            C,I,79   "semi-colon"

          sys --   (compiling)         

...  sys is balanced with its corresponding : .
See:  EXIT  :  "stack, return"  "9.4 Compilation"

It also makes it possible to implement :NONAME without explicitly using [ SMUDE ] in the source and without accidently smudging the latest name and then unsmudging it, as it may be needed by the headless word being compiled by :NONAME .


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 13, 2019 10:30 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
I haven't implemented :NONAME but I was looking at Leo Brodie's DOER/MAKE from Thinking Forth. I got it working with Fleet Forth but it started me thinking that I might want to change semicolon's ( ; ) sys just a little.
Code:
( ADDR TRUE -- )  There is a dictionary entry which needs revealed.
( FALSE -- )  There is not.

Or possibly
Code:
( ADDR TRUE -- )  There is a dictionary entry which needs revealed.
( FALSE FALSE -- )  There is not.

To keep both versions of semicolon's sys the same size ( same number of stack entries ).
Since TRUE and FALSE are not used as compiler security numbers for any of the control flow words, this shouldn't be a problem.
Any comments?

P.S. Or possibly
Code:
( ADDR TRUE -- )  There is a dictionary entry which needs revealed.
( CFA FALSE -- CFA )  There is not, but there is the CFA of the headless word which gets left on the data stack


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 13, 2019 10:44 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
JimBoyd wrote:
Fleet Forth has a word BYE that returns to basic by way of the processor's system reset hardware vector at $FFFC.

There is slightly more to BYE than that.
Code:
: BYE  ( -- )
   SAVE-BUFFERS
   ACLOSE
   0FFFC EXECUTE ;

Save the block buffers, close all files, then restart the system.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 19, 2019 11:25 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
I don't know why I didn't think of this sooner, but I can make BYE even smaller.
Code:
: BYE  ( -- )
   SAVE-BUFFERS
   ACLOSE
   [ 0FFFC , ] ;
-2 ALLOT  // RECLAIM MEMORY USED BY UNNEEDED EXIT


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 11, 2019 9:41 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
I moved CO ( coroutine) and RB ( restore base) from the system loader to the kernel.
CO is a word that allows two words to be coroutines and RB used in a word causes the base to be restored, when the word exits, to what it was prior to the execution of RB .
My preference is that words, like DUMP and SEE , do not alter BASE. If I want to SEE in hexadecimal I'll say HEX SEE <SOME.WORD> . If I want a decimal dump I'll say DECIMAL <some address> <some count> DUMP . There are certain situations where this doesn't work. When communicating with a Commodore disk drive over the command channel, the command is a text string including the numbers for disk ( 0 or 1), track, and sector. In the Fleet Forth kernel, I use some of the pictured numeric words to build a text string, but BASE has to be decimal. By moving RB to the kernel, I can start the word with RB DECIMAL .
Having RB in the kernel necessitated the inclusion of CO . Here are their definitions.
Code:
SCR# 9C
// CO RB
HEX
// COROUTINES
: CO   2R> SWAP 2>R ;
// RESTORE BASE AT END OF WORD
// CALLING RB
: RB  ( -- )
   BASE @ R> 2>R  CO
   R> BASE ! ;

A note about 2>R ( and 2R> ), When moving two cells ( four bytes in this case ) from one stack to the other, the byte order is preserved. When two cells are moved from the data stack, as in this case, the value that was on top of the data stack will be the one that is on top of the return stack. As an example, CO could have been defined as:
Code:
: CO   2R>  >R >R ;

or
Code:
: CO   R> R>  2>R ;

For the newcomers to Forth, I will attempt an explanation of how RB works.
Get the value of BASE.
Pull the return address off the return stack ( the return point in the calling word.)
Move both to the return stack with the value of BASE tucked under the return address of the calling word.
CO is executed which places IP on the stack.
CO switches the two addresses and returns to the word that called RB .
When that word EXITs, RB resumes execution at the point after CO.
The previous value of BASE is still on the return stack and is transfered to the data stack and stored in BASE.

I don't remember where I saw CO , but I knew it would be useful. The other place it is used is in the definition of WITH-WORDS .
Code:
SCR# 38
// WITH-WORDS WORDS
HEX
: WITH-WORDS  ( -- NFA )
   COLS ?CR
   R>  CONTEXT @
   BEGIN
      @ DUP DONE? 0= AND
   WHILE
      2DUP 2>R  L>NAME
      SWAP >R CO  2R>
   REPEAT
   2DROP ;

Here is an example of its use in WORDS
Code:
: WORDS  ( -- )
   WITH-WORDS DUP C@ 1F AND 1+ ?CR
   ID. TAB ;

For each word in the CONTEXT VOCABULARY , the code following WITH-WORDS through the EXIT compiled by semicolon is executed with the address of the word's name field on the data stack.


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 17, 2019 10:41 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
I mentioned in another post that BLOCK and BUFFER are code definitions and BUFFER's code field points one byte into BLOCK's body. Here is how that came about. When a block is not the most recently used, BLOCK checks the buffer table. If it is in the table, the buffer number ( 1 - #BUF ) is returned. If it's not in the table, #BUF is placed on the data stack ( 0 is the phantom entry.) A flag is placed on the stack as well. If the flag is FALSE, the requested block does not need read from mass storage, it's already in a buffer. If the flag is TRUE then the block is read from mass storage. It occurred to me that when the flag is FALSE there is no difference between the behavior of BLOCK and BUFFER . A value, T/F , was added and the words used only by BLOCK and BUFFER were consolidated into BLOCK. The flag placed on the stack by that part of BLOCK is now FALSE to not read a block from mass storage and T/F to maybe read a block from mass storage.
Maybe read a block? That sounds iffy. It really is reliable.
Fleet Forth is an ITC Forth and NEXT always leaves the Y-register set to zero. The first thing BLOCK does is increment the Y-register and store it into both bytes of T/F's parameter field. BUFFER's code field points past the Y-increment so it stores a FALSE in T/F's parameter field. For BLOCK , T/F is always TRUE and for BUFFER , T/F is always FALSE .


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 17, 2019 10:47 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
JimBoyd wrote:
CO is a word that allows two words to be coroutines and RB used in a word causes the base to be restored, when the word exits, to what it was prior to the execution of RB .

One caveat I forgot to mention but should be obvious. If RB is used in a word that ABORT's ( including ABORT" CCC" ) or calls QUIT directly or indirectly, BASE will not, can not, be restored.


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 20, 2019 9:13 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
JimBoyd wrote:
Here is an example of its use in WORDS
Code:
: WORDS  ( -- )
   WITH-WORDS DUP C@ 1F AND 1+ ?CR
   ID. TAB ;

For each word in the CONTEXT VOCABULARY , the code following WITH-WORDS through the EXIT compiled by semicolon is executed with the address of the word's name field on the data stack.

I would also like to mention that factoring WITH-WORDS out of WORDS makes it possible to define words to work with names in the dictionary without knowing how the dictionary ( header) is implemented. It also makes it easier.
here is a log of a session.
Code:
 OK
VARIABLE WIDTH  OK
: (NAME-LENGTH)
0 WITH-WORDS
C@ 1F AND WIDTH @ = - ;  OK
1 WIDTH ! (NAME-LENGTH) .
1B  OK
DECIMAL  OK
: NAME-LENGTH  32 1 DO
I WIDTH ! (NAME-LENGTH) I 5 U.R 5 U.R
LOOP ;  OK
0 0 JIFFY! NAME-LENGTH JIFFY@ CR D.
    1   27
    2   56
    3   90
    4   99
    5  112
    6   81
    7   56
    8   35
    9   12
   10    5
   11    3
   12    3
   13    2
   14    0
   15    0
   16    0
   17    0
   18    0
   19    0
   20    0
   21    0
   22    0
   23    0
   24    0
   25    0
   26    0
   27    0
   28    0
   29    0
   30    0
   31    0
2676  OK
2676 60 /MOD . . 44 36  OK
CONSOLE  OK

A relatively simple way to get data on the name lengths in the Forth vocabulary even if it did take 44.6 seconds. It would be fairly easy to define an array of 32 cells and accumulate results for all vocabularies used. I hope this bare bones example shows how useful WITH-WORDS can be.
Another utility word which might be useful for new users of Fleet Forth ( When I finally finish making modifications and write the documentation so I can release it) is IN-NAME which uses WITH-WORDS and MATCH. As an example, a new user checking the glossary for the word OPEN will soon find that it doesn't exist and wonder how to open a disk for BLOCK access. Searching the entire glossary can be avoided by typing " OPEN" IN-NAME <carriage return or enter>. A list of all words in the context vocabulary with 'open' in their name will be displayed. The only two in the Forth vocabulary are DOPEN and (OPEN). A quick glossary check will reveal that DOPEN is the desired command. This example is just a bit contrived as I do plan to include a getting started guide, but you get the idea.


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 20, 2019 9:33 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
Fleet Forth includes EVALUATE in the system loader and support for it in the kernel. This version of EVALUATE takes an address and a count on the data stack. The word QUERY EXPECT's a text string and stores it in TIB. In Fleet Forth, TIB is more like a VALUE than a CONSTANT and QUERY sets TIB to the proper address ( $2A7). EVALUATE saves the contents of BLK >IN #TIB and TIB to the return stack. It sets TIB to the address of the string to be evaluated, stores the length in #TIB , turns BLK and >IN off, then calls INTERPRET . Finally, all the saved values are restored.
Here is the code for QUERY in the kernel.
Code:
: QUERY  ( -- )
   [ 'TIB ] LITERAL IS TIB
   TIB 50 EXPECT  SPAN @ DUP #TIB !
   1+ #OUT +!
   BLK OFF >IN OFF ;

The DUP and the line with
Code:
   1+ #OUT +!

have to do with output formatting and can be safely ignored.
The code for EVALUATE in the system loader.
Code:
SCR# 2C
// EVALUATE
HEX
// NESTABLE EVALUATE
: EVALUATE  ( ADR N -- )
   BLK @ >IN @ 2>R
   TIB #TIB @ 2>R
   #TIB ! IS TIB
   BLK OFF >IN OFF
   INTERPRET
   2R> #TIB ! IS TIB
   2R> >IN ! BLK ! ;

I'm wondering if there is a better way to implement EVALUATE within the parameters of the Forth-83 standard?


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 24, 2019 7:10 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
I implemented part of the ANSForth test suite to test EVALUATE . I only implemented part of it because Fleet Forth is a Forth-83 standard Forth and because it does not have floating point. Here is my version of the test suite. In places where there is <[ or ]>, that's because the C64 lacks the curly braces { }.
Code:
SCR# 6C
// TEST WORDS
HEX
CREATE SB1 80 ALLOT
CREATE SB2 80 ALLOT
: T<[
   SB1 80 ERASE  SB2 80 ERASE
   ?EXEC <[ ; IMMEDIATE
: ->
   ?EXEC ]> 0
   ?DO  I 2* SB1 + !  LOOP
   <[ ; IMMEDIATE
: ]>T
   ?EXEC ]> 0
   ?DO  I 2* SB2 + !  LOOP
   SB1 80 SB2 -TEXT 0<> ABORT" FAIL"
   CR ." PASS" ; IMMEDIATE

SCR# 6D
// S"
HEX
: S"
   [COMPILE] "
   STATE @ IF  COMPILE  THEN
   COUNT ; IMMEDIATE

<[ and ]> are used to count the number of items on the data stack between <[ and ]>, kind of like Garth's { and } .
-TEXT takes an address, a count and a second address as parameters and returns a flag ( addr1 cnt addr2. -- flag ). It performs a byte by byte comparison until it reaches the end of the count unless it finds a difference first. if both strings are identical, it returns a zero. The contents don't have to be text strings, -TEXT works just as well with strings of binary data.
here are the tests I ran.
Code:
SCR# 6E
// EVALUATE TEST
RB DECIMAL
: GE1 S" 123" ; IMMEDIATE
: GE2 S" 123 1+" ; IMMEDIATE
: GE3 S" : GE4 345 ;" ;
: GE5 EVALUATE ; IMMEDIATE
T<[ GE1 EVALUATE -> 123 ]>T
T<[ GE2 EVALUATE -> 124 ]>T
T<[ GE3 EVALUATE ->     ]>T
T<[ GE4          -> 345 ]>T
T<[ : GE6 GE1 GE5 ; -> ]>T
T<[ GE6 -> 123 ]>T
T<[ : GE7 GE2 GE5 ; -> ]>T
T<[ GE7 -> 124 ]>T

I also ran a variation of these tests. EVALUATE is supposed to be nestable, isn't it?
Code:
SCR# 6F
// EVALUATE TEST
RB DECIMAL
: GE1 S" 123" ; IMMEDIATE
: GE2 S" 123 1+" ; IMMEDIATE
: GE3 S" : GE4 345 ;" ;
: GE5 EVALUATE ; IMMEDIATE
S" T<[ GE1 EVALUATE ->" EVALUATE 123 ]>T
S" T<[ GE2 EVALUATE ->" EVALUATE 124 ]>T
S" T<[ GE3 EVALUATE ->" EVALUATE     ]>T
S" T<[ GE4          ->" EVALUATE 345 ]>T
S" T<[ : GE6 GE1 GE5 ; ->" EVALUATE ]>T
S" T<[ GE6 ->" EVALUATE 123 ]>T
S" T<[ : GE7 GE2 GE5 ; ->" EVALUATE ]>T
S" T<[ GE7 ->" EVALUATE 124 ]>T

Here are the results.
Code:
 OK
6E LOAD
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS OK
FORGET GE1  OK
6F LOAD
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS OK
CONSOLE


Cheers,
Jim


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 24, 2019 7:17 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
Oops, I made one minor mistake with my test words. I didn't save the count returned by ]> .
Here is the corrected code. I'll have to wait till I get home to test it and retest EVALUATE .
Code:
SCR# 6C
// TEST WORDS
HEX
CREATE SB1 80 ALLOT
CREATE SB2 80 ALLOT
: T<[
   SB1 80 ERASE  SB2 80 ERASE
   ?EXEC <[ ; IMMEDIATE
: ->
   ?EXEC ]> DUP SB1 C!  0
   ?DO  I 2* SB1 + 1+ !  LOOP
   <[ ; IMMEDIATE
: ]>T
   ?EXEC ]> DUP SB2 C!  0
   ?DO  I 2* SB2 + 1+ !  LOOP
   SB1 80 SB2 -TEXT 0<> ABORT" FAIL"
   CR ." PASS" ; IMMEDIATE

By the way, the word ?EXEC aborts if compiling.

[Edit: corrected a typo]


Last edited by JimBoyd on Mon Feb 25, 2019 9:29 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 24, 2019 7:40 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
In Fleet Forth, I treat some of the CONSTANTs more like VALUEs. I was wondering if it would be worth the overhead in memory to implement VALUEs and redefine IS and (IS) to only work on VALUEs and DEFERed words. After all, not everything in Fleet Forth that appears to be a CONSTANT is one. The words TRUE , FALSE , 0 , and 1 have no parameter field. Their code fields point to code elsewere. The C64 has 16 colors, but the color CONSTANT's in Fleet Forth were changed to code to save memory.
Code:
SCR# 37
// COLORS
HEX
CODE LT-GREY  ( -- 0F )
   INY, INY, INY, INY, INY,
   INY, INY, INY, INY, INY,
   INY, INY, INY, INY, INY,
   TYA,  APUSH JMP,  END-CODE
CREATE LT-BLUE   -2 ALLOT
   ' LT-GREY  @ 1+ ,
CREATE LT-GREEN  -2 ALLOT
   ' LT-BLUE  @ 1+ ,
CREATE MD-GREY   -2 ALLOT
   ' LT-GREEN @ 1+ ,
CREATE DK-GREY   -2 ALLOT
   ' MD-GREY  @ 1+ ,

SCR# 38
// COLORS
HEX
CREATE LT-RED    -2 ALLOT
   ' DK-GREY  @ 1+ ,
CREATE BROWN     -2 ALLOT
   ' LT-RED   @ 1+ ,
CREATE ORANGE    -2 ALLOT
   ' BROWN    @ 1+ ,
CREATE YELLOW    -2 ALLOT
   ' ORANGE   @ 1+ ,
CREATE BLUE      -2 ALLOT
   ' YELLOW   @ 1+ ,
CREATE GREEN     -2 ALLOT
   ' BLUE     @ 1+ ,
CREATE PURPLE    -2 ALLOT
   ' GREEN    @ 1+ ,

SCR# 39
// COLORS
HEX
CREATE CYAN      -2 ALLOT
   ' PURPLE   @ 1+ ,
CREATE RED       -2 ALLOT
   ' CYAN     @ 1+ ,
CREATE WHITE     -2 ALLOT
   ' RED      @ 1+ ,
CREATE BLACK     -2 ALLOT
   ' WHITE    @ 1+ ,

Although the parameter field for LT-GREY is 19 bytes, the other color words have no parameter field.


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 25, 2019 9:32 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
JimBoyd wrote:
Oops, I made one minor mistake with my test words. I didn't save the count returned by ]> .
Here is the corrected code. I'll have to wait till I get home to test it and retest EVALUATE .

Tested and works. EVALUATE still passes when loaded from a BLOCK and from the keyboard:
Code:
DECIMAL  OK
: GE1 S" 123" ; IMMEDIATE  OK
: GE2 S" 123 1+" ; IMMEDIATE  OK
: GE3 S" : GE4 345 ;" ;  OK
: GE5 EVALUATE ; IMMEDIATE  OK
T<[ GE1 EVALUATE -> 123 ]>T
PASS OK
T<[ GE2 EVALUATE -> 124 ]>T
PASS OK
T<[ GE3 EVALUATE ->     ]>T
PASS OK
T<[ GE4          -> 345 ]>T
PASS OK
T<[ : GE6 GE1 GE5 ; -> ]>T
PASS OK
T<[ GE6 -> 123 ]>T
PASS OK
T<[ : GE7 GE2 GE5 ; -> ]>T
PASS OK
T<[ GE7 -> 124 ]>T
PASS OK
CONSOLE


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 25, 2019 9:39 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858
JimBoyd wrote:
In Fleet Forth, I treat some of the CONSTANTs more like VALUEs. I was wondering if it would be worth the overhead in memory to implement VALUEs and redefine IS and (IS) to only work on VALUEs and DEFERed words.

(IS) stayed the same. Adding VALUE to the kernel only added 17 bytes. Here's the code:
Code:
SCR# 90
// CONSTANT VALUE
HEX
: CONSTANT  ( N -- )
   CREATE , ;CODE  ( -- N )
   LABEL CONSTANT.CODE
   2 # LDY,
   W )Y LDA,  PHA,  INY,
   W )Y LDA,
   PUSH JMP,  END-CODE
: VALUE  ( N -- )
   CONSTANT  ;CODE  ( -- N )
   CONSTANT.CODE JMP,
   END-CODE

And the new IS ( defined in the system loader):
Code:
: IS  ( -- )
   ' DUP @
   DUP [ ' #BUF @ ] LITERAL <>
   SWAP [ ' TYPE @ ] LITERAL <> AND
   ABORT" CAN'T SET"
   STATE @
   IF  COMPILE (IS) , EXIT  THEN
   >BODY ! ; IMMEDIATE

#BUF is a VALUE and TYPE is a DEFERred word.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 338 posts ]  Go to page Previous  1, 2, 3, 4, 5 ... 23  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: