tschak909 Posted October 30, 2022 Share Posted October 30, 2022 There is a ready to run version of @dmsc's excellent FastBASIC 4.4 in the @ABBUC Public Domain library, complete with manual and example programs. This is a great way to quickly write programs that take full advantage of the #Atari8bit, and with the #FujiNet, you can quickly access it using the abbuc.social TNFS! Try it today! 2 Quote Link to comment Share on other sites More sharing options...
dmsc Posted October 30, 2022 Share Posted October 30, 2022 Hi! 4 hours ago, tschak909 said: There is a ready to run version of @dmsc's excellent FastBASIC 4.4 in the @ABBUC Public Domain library, complete with manual and example programs. This is a great way to quickly write programs that take full advantage of the #Atari8bit, and with the #FujiNet, you can quickly access it using the abbuc.social TNFS! Try it today! Great! Note that current version of FastBasic is 4.6, you can get the image from https://github.com/dmsc/fastbasic/releases/tag/v4.6 , would be cool if you could always get the last version directly from the net. Version 4.6 has a lot of new features compared with v4.4. Also, we could prepare a special version with more FujiNET support - what do you think could be added? I don't follow the new developments, so I don't know all the features. Simple ones that I think could be feasible: - Loadable from network OS, replacing all "D:" with "N:". - Adding some statements that call XIO with correct string parameters. Have Fun! 3 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 31, 2022 Author Share Posted October 31, 2022 Hi @dmsc! We could definitely do some interesting things here. Let me see if I can easily explain how to talk to FujiNet: Everything happens over SIO. Every single FujiNet command is done over SIO, so you: * Set the Device Command Block (DCB) with the command you want to do * Call SIOV * Error code in DSTATS. So even a simple SIO statement that takes calls to fill up the DCB would be REALLY useful here. Currently, in addition to the legacy disk devices (Device ID's $31-$38), the printer devices ($40-$44), and the serial device ($50), there are: * The FUJI control device $70 - to do things like mount slots. The CONFIG program deals with this device, but anything can talk to it. (https://github.com/FujiNetWIFI/fujinet-platformio/wiki/SIO-Commands-for-Device-ID-%2470) * The Network devices $71 - $78, which give access to all sorts of protocol adapters (TCP, UDP, HTTPS, TNFS, etc.) (https://github.com/FujiNetWIFI/fujinet-platformio/wiki/SIO-Commands-for-Device-IDs-%2471-to-%2478) The Network devices are very unique among SIO devices, because they are the only known SIO peripheral to use the interrupt lines to signal when data is ready (the PROCEED line.) for the computer to pick up. So for example, the NETCAT example program that provides a dumb terminal will install a simple interrupt handler on VPRCED to set a variable (I called it TRIP) whenever there is data waiting. This avoids noisy STATUS traffic asking "is there something for me, yet?" So we can at the simplest, check a variable, and if it gets set, we call STATUS to get # of bytes waiting, and then a READ. There is also a third mode, UDP streaming, specifically for arcade game interaction. https://github.com/FujiNetWIFI/fujinet-platformio/wiki/SIO-Command-%24F0-Enable-UDPStream-Mode To initially support MidiMaze, we added a command to the FUJI device, which takes over the SIO bus, and reflects data coming in from a specific UDP port and streams it to the computer. (the FujiNet also turns on a clock, and expects the Atari to synchronize to it. RThis will allow for very high transmission rates.) While this will require special software setup from the Atari side (e.g. new VSERIN/VSEROUT routines), it has the most potential to bring arcade style network interaction. Some things to think about,. -Thom 1 Quote Link to comment Share on other sites More sharing options...
dmsc Posted October 31, 2022 Share Posted October 31, 2022 Hi! 1 hour ago, tschak909 said: Hi @dmsc! We could definitely do some interesting things here. Let me see if I can easily explain how to talk to FujiNet: Everything happens over SIO. Every single FujiNet command is done over SIO, so you: * Set the Device Command Block (DCB) with the command you want to do * Call SIOV * Error code in DSTATS. FastBASIC can call assembly routines directly, so you can already convert some of the C programs. This is an (untested) program to read the last version from github releases and print it to screen, using the JSON SIO support: ' FujiNET Sample: Gets last FastBASIC version from github. ' Open FujiNET SIO device PROC nopen unit addr aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $4F ' DCOMND (Open) POKE $303, $80 ' DSTATS DPOKE $304, addr ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Close FujiNET SIO device PROC nclose unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $43 ' DCOMND (Close) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, 0 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Read from FujiNET SIO device PROC nread unit addr rlen POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $52 ' DCOMND (Read) POKE $303, $40 ' DSTATS DPOKE $304, addr ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, rlen ' DBYT DPOKE $30A, rlen ' DAUX1/DAUX2 EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Get status from FujiNET SIO device PROC nstatus unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $53 ' DCOMND (Status) POKE $303, $40 ' DSTATS DPOKE $304, $2EA ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 4 ' DBYT DPOKE $30A, 0 ' DAUX1/DAUX2 EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Parse JSON internal buffer PROC njsonparse unit aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $40 ' DCOMND (Parse) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query JSON from parsed PROC njsonquery unit aux1 addr POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $51 ' DCOMND (Query) POKE $303, $80 ' DSTATS DPOKE $304, addr ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Set channel mode PROC nchanmode unit aux1 mode POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $FC ' DCOMND (mode) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, mode ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query one element from the JSON PROC query str @njsonquery 1, $0C, str IF EC<>1 THEN @ShowError @nstatus 1 IF EC<>1 THEN @ShowError dlen = DPEEK($2EA) ' DVSTAT RESP$="-NONE-" if dlen if dlen > 255 then dlen = 255 @nread 1, &RESP$, dlen IF EC<>1 THEN @ShowError endif ENDPROC ' Shows an error and terminates PROC ShowError ? ""$9B$FD"ERROR - " ; EC ;""$FD @nclose 1 @ExitKey ENDPROC ' Get's a key and exists PROC ExitKey ? "PRESS ANY KEY"; REPEAT : UNTIL KEY() END ENDPROC ' Main program URI$ = "N:HTTPS://api.github.com/repos/dmsc/fastbasic/releases/latest"$9B EC = 0 ' Open URI ? "Opening:"$9B; URI$; @nopen 1, &URI$, $0C IF EC<>1 THEN @ShowError ' Switch to JSON mode @nchanmode 1, $0C, 1 IF EC<>1 THEN @ShowError ' And parse @njsonparse 1, $0C IF EC<>1 THEN @ShowError ' Query some properties: @query & "name"$9B ? "Last FastBASIC version: "; RESP$ @query & "published_at"$9B ? "Released at: "; RESP$ @query & "published_at"$9B ? "Released at: "; RESP$ @nclose 1 ? "--------------------------" @ExitKey Attached is a test disk with the source and compiled version - should autoboot to the program, with no DOS it should work via pure SIO, is that so? Have Fun! fb-fuji-test.atr gitver.bas gitver.xex 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 31, 2022 Author Share Posted October 31, 2022 Looks like it from first glance, will test in a bit (I am adding high score support to a BASIC game, Goldrush, in preparation for an ABBUC article I am writing.) -Thom 2 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 31, 2022 Author Share Posted October 31, 2022 @dmsc Yup, it works, you must make sure that you read exactly the # of bytes needed (STATUS is good for this). The hearts are from asking for too much data in the read. (not sure why the first char returned is being chopped). This can be debugged from @apc's fujinet-pc and Altirra. I had to change the DCOMND for QUERY from $40 to $50 ('P'), and had to add N:/ to the query strings below (yes, it's odd, but it's so that it just works from CIO in BASIC) ' FujiNET Sample: Gets last FastBASIC version from github. ' Open FujiNET SIO device PROC nopen unit addr aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $4F ' DCOMND (Open) POKE $303, $80 ' DSTATS DPOKE $304, addr ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Close FujiNET SIO device PROC nclose unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $43 ' DCOMND (Close) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, 0 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Read from FujiNET SIO device PROC nread unit addr rlen POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $52 ' DCOMND (Read) POKE $303, $40 ' DSTATS DPOKE $304, addr ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, rlen ' DBYT DPOKE $30A, rlen ' DAUX1/DAUX2 EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Get status from FujiNET SIO device PROC nstatus unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $53 ' DCOMND (Status) POKE $303, $40 ' DSTATS DPOKE $304, $2EA ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 4 ' DBYT DPOKE $30A, 0 ' DAUX1/DAUX2 EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Parse JSON internal buffer PROC njsonparse unit aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $50 ' DCOMND (Parse) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query JSON from parsed PROC njsonquery unit aux1 addr POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $51 ' DCOMND (Query) POKE $303, $80 ' DSTATS DPOKE $304, addr ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Set channel mode PROC nchanmode unit aux1 mode POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $FC ' DCOMND (mode) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, mode ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query one element from the JSON PROC query str @njsonquery 1, $0C, str IF EC<>1 THEN @ShowError @nstatus 1 IF EC<>1 THEN @ShowError dlen = DPEEK($2EA) ' DVSTAT RESP$="-NONE-" if dlen if dlen > 255 then dlen = 255 @nread 1, &RESP$, dlen IF EC<>1 THEN @ShowError endif ENDPROC ' Shows an error and terminates PROC ShowError ? ""$9B$FD"ERROR - " ; EC ;""$FD @nclose 1 @ExitKey ENDPROC ' Get's a key and exists PROC ExitKey ? "PRESS ANY KEY"; REPEAT : UNTIL KEY() END ENDPROC ' Main program URI$ = "N:HTTPS://api.github.com/repos/dmsc/fastbasic/releases/latest"$9B EC = 0 ' Open URI ? "Opening:"$9B; URI$; @nopen 1, &URI$, $0C IF EC<>1 THEN @ShowError ' Switch to JSON mode @nchanmode 1, $0C, 1 IF EC<>1 THEN @ShowError ' And parse @njsonparse 1, $0C IF EC<>1 THEN @ShowError ' Query some properties: @query & "N:/name"$9B ? "Last FastBASIC version: "; RESP$ @query & "N:/published_at"$9B ? "Released at: "; RESP$ @query & "N:/published_at"$9B ? "Released at: "; RESP$ @nclose 1 ? "--------------------------" @ExitKey This is indeed very promising. The real question is, how could we get things in so that we could submit FujiNet things for 10 liner BASIC contests? -Thom 2 Quote Link to comment Share on other sites More sharing options...
dmsc Posted October 31, 2022 Share Posted October 31, 2022 Hi! 1 minute ago, tschak909 said: @dmsc Yup, it works, you must make sure that you read exactly the # of bytes needed (STATUS is good for this). The hearts are from asking for too much data in the read. (not sure why the first char returned is being chopped). Thanks for trying it out! The problem with the strings is that I goofed the addresses - in FastBASIC the first byte in a string is the length, and it is being overwritten here with the first character. This version should work better, as it sets the string length to the correct value: ' FujiNET Sample: Gets last FastBASIC version from github. ' Open FujiNET SIO device PROC nopen unit addr aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $4F ' DCOMND (Open) POKE $303, $80 ' DSTATS DPOKE $304, addr + 1 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Close FujiNET SIO device PROC nclose unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $43 ' DCOMND (Close) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, 0 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Read from FujiNET SIO device PROC nread unit addr rlen POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $52 ' DCOMND (Read) POKE $303, $40 ' DSTATS DPOKE $304, addr + 1 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, rlen ' DBYT DPOKE $30A, rlen ' DAUX1/DAUX2 POKE addr, rlen EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Get status from FujiNET SIO device PROC nstatus unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $53 ' DCOMND (Status) POKE $303, $40 ' DSTATS DPOKE $304, $2EA ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 4 ' DBYT DPOKE $30A, 0 ' DAUX1/DAUX2 EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Parse JSON internal buffer PROC njsonparse unit aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $50 ' DCOMND (Parse) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query JSON from parsed PROC njsonquery unit aux1 addr POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $51 ' DCOMND (Query) POKE $303, $80 ' DSTATS DPOKE $304, addr+1 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Set channel mode PROC nchanmode unit aux1 mode POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $FC ' DCOMND (mode) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, mode ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query one element from the JSON PROC query str @njsonquery 1, $0C, str IF EC<>1 THEN @ShowError @nstatus 1 IF EC<>1 THEN @ShowError dlen = DPEEK($2EA) ' DVSTAT RESP$="-NONE-" if dlen if dlen > 255 then dlen = 255 @nread 1, &RESP$, dlen IF EC<>1 THEN @ShowError endif ENDPROC ' Shows an error and terminates PROC ShowError ? ""$9B$FD"ERROR - " ; EC ;""$FD @nclose 1 @ExitKey ENDPROC ' Get's a key and exists PROC ExitKey ? "PRESS ANY KEY"; REPEAT : UNTIL KEY() END ENDPROC ' Main program URI$ = "N:HTTPS://api.github.com/repos/dmsc/fastbasic/releases/latest"$9B EC = 0 ' Open URI ? "Opening:"$9B; URI$; @nopen 1, &URI$, $0C IF EC<>1 THEN @ShowError ' Switch to JSON mode @nchanmode 1, $0C, 1 IF EC<>1 THEN @ShowError ' And parse @njsonparse 1, $0C IF EC<>1 THEN @ShowError ' Query some properties: @query & "N:/name"$9B ? "Last FastBASIC version: "; RESP$ @query & "N:/published_at"$9B ? "Released at: "; RESP$ @query & "N:/created_at"$9B ? "Created at: "; RESP$ @nclose 1 ? "--------------------------" @ExitKey Have Fun! 3 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 1, 2022 Author Share Posted November 1, 2022 23 hours ago, dmsc said: Hi! Thanks for trying it out! The problem with the strings is that I goofed the addresses - in FastBASIC the first byte in a string is the length, and it is being overwritten here with the first character. This version should work better, as it sets the string length to the correct value: ' FujiNET Sample: Gets last FastBASIC version from github. ' Open FujiNET SIO device PROC nopen unit addr aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $4F ' DCOMND (Open) POKE $303, $80 ' DSTATS DPOKE $304, addr + 1 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Close FujiNET SIO device PROC nclose unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $43 ' DCOMND (Close) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, 0 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Read from FujiNET SIO device PROC nread unit addr rlen POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $52 ' DCOMND (Read) POKE $303, $40 ' DSTATS DPOKE $304, addr + 1 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, rlen ' DBYT DPOKE $30A, rlen ' DAUX1/DAUX2 POKE addr, rlen EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Get status from FujiNET SIO device PROC nstatus unit POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $53 ' DCOMND (Status) POKE $303, $40 ' DSTATS DPOKE $304, $2EA ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 4 ' DBYT DPOKE $30A, 0 ' DAUX1/DAUX2 EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Parse JSON internal buffer PROC njsonparse unit aux1 POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $50 ' DCOMND (Parse) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query JSON from parsed PROC njsonquery unit aux1 addr POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $51 ' DCOMND (Query) POKE $303, $80 ' DSTATS DPOKE $304, addr+1 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 256 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, 0 ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Set channel mode PROC nchanmode unit aux1 mode POKE $300, $71 ' DDEVIC POKE $301, unit ' DUNIT POKE $302, $FC ' DCOMND (mode) POKE $303, $00 ' DSTATS DPOKE $304, 0 ' DBUF POKE $306, $1F ' DTIMLO (TIMEOUT) DPOKE $308, 0 ' DBYT POKE $30A, aux1 ' DAUX1 POKE $30B, mode ' DAUX2 (no translation) EC = USR($E459) EC = PEEK($303) ' DSTATS ENDPROC ' Query one element from the JSON PROC query str @njsonquery 1, $0C, str IF EC<>1 THEN @ShowError @nstatus 1 IF EC<>1 THEN @ShowError dlen = DPEEK($2EA) ' DVSTAT RESP$="-NONE-" if dlen if dlen > 255 then dlen = 255 @nread 1, &RESP$, dlen IF EC<>1 THEN @ShowError endif ENDPROC ' Shows an error and terminates PROC ShowError ? ""$9B$FD"ERROR - " ; EC ;""$FD @nclose 1 @ExitKey ENDPROC ' Get's a key and exists PROC ExitKey ? "PRESS ANY KEY"; REPEAT : UNTIL KEY() END ENDPROC ' Main program URI$ = "N:HTTPS://api.github.com/repos/dmsc/fastbasic/releases/latest"$9B EC = 0 ' Open URI ? "Opening:"$9B; URI$; @nopen 1, &URI$, $0C IF EC<>1 THEN @ShowError ' Switch to JSON mode @nchanmode 1, $0C, 1 IF EC<>1 THEN @ShowError ' And parse @njsonparse 1, $0C IF EC<>1 THEN @ShowError ' Query some properties: @query & "N:/name"$9B ? "Last FastBASIC version: "; RESP$ @query & "N:/published_at"$9B ? "Released at: "; RESP$ @query & "N:/created_at"$9B ? "Created at: "; RESP$ @nclose 1 ? "--------------------------" @ExitKey Have Fun! What does it take to add a new command to FastBASIC? I think we could add some commands to make talking to FuijNet _REALLY_ simple. You really do the same things, over and over again. -Thom Quote Link to comment Share on other sites More sharing options...
dmsc Posted November 3, 2022 Share Posted November 3, 2022 Hi! On 10/31/2022 at 11:59 PM, tschak909 said: What does it take to add a new command to FastBASIC? I think we could add some commands to make talking to FuijNet _REALLY_ simple. You really do the same things, over and over again. It is moderately easy, I tried to document it in https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md#extending-the-language . I will try to summarize bellow: First: Adding a statement to the cross compiler. This is the simplest part, as you don't need to recompile, only add new rules to the existing files. Looking at the repeating code, adding a "SIO" statement, similar to the existing "XIO", should simplify it a lot. In this case, the syntax for njsonquery could be something like: SIO $71, unit, $51, $80, addr+1, $1F, 256, aux1, 0 Now, to implement this, first we need to create a new target file, for example, named "fujinet.tgt": # FujiNet extended target include default syntax fujinet.syn This simply states that the fujinet target is copied from the default and adds new syntax definitions from the "fujinet.syn" file. Now, in the syntax folder, we create the file fujinet.syn with the contents: STATEMENT: "SIo" EXPR emit { TOK_NUM_POKE, &$300 } \ "," EXPR emit { TOK_NUM_POKE, &$301 } \ "," EXPR emit { TOK_NUM_POKE, &$302 } \ "," EXPR emit { TOK_NUM_POKE, &$303 } \ "," emit { TOK_NUM, &$304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ "," EXPR emit { TOK_NUM_POKE, &$306 } \ "," emit { TOK_NUM, &$308, TOK_SADDR } EXPR emit { TOK_DPOKE } \ "," EXPR emit { TOK_NUM_POKE, &$30A } \ "," EXPR emit { TOK_NUM_POKE, &$30B } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } INT_FUNCTIONS: "SErr()" emit { TOK_NUM, &$303, TOK_PEEK } This looks complicated, but it is simply adds two parsing rules: - A statement parsing rule that expects the word "SIO" (or "SI."), then 9 integer expressions, the "byte" expressions are simpler, as they get translated directly to a POKE to the given address, the "word" expressions need to use the "DPOKE" token, expecting the address in the SADDR register. Note that all literal 16 bit values need an "&" before. After all that preparation, the assembly routine at $E459 is called, and the returned value is simply discarded. - A function parsing rule, that expects "SERR()" (or "SE.") and simply returns the PEEK of address $303. With this changes, you can compile the test program using: fb -t:fujinet gitver2.bas This is the test program using the new "SIO" statement: ' FujiNET Sample: Gets last FastBASIC version from github. ' Open FujiNET SIO device PROC nopen unit addr aux1 SIO $71, unit, $4F, $80, addr+1, $1F, 256, aux1, 0 ENDPROC ' Close FujiNET SIO device PROC nclose unit SIO $71, unit, $43, $00, 0, $1F, 0, 0, 0 ENDPROC ' Read from FujiNET SIO device PROC nread unit addr rlen SIO $71, unit, $52, $40, addr+1, $1F, rlen, rlen, 0 POKE addr, rlen ENDPROC ' Get status from FujiNET SIO device PROC nstatus unit SIO $71, unit, $53, $40, $2EA, $1F, 4, 0, 0 ENDPROC ' Parse JSON internal buffer PROC njsonparse unit aux1 SIO $71, unit, $50, $00, 0, $1F, 0, aux1, 0 ENDPROC ' Query JSON from parsed PROC njsonquery unit aux1 addr SIO $71, unit, $51, $80, addr+1, $1F, 256, aux1, 0 ENDPROC ' Set channel mode PROC nchanmode unit aux1 mode SIO $71, unit, $FC, $00, 0, $1F, 0, aux1, mode ENDPROC ' Query one element from the JSON PROC query str @njsonquery 1, $0C, str IF SERR()<>1 THEN @ShowError @nstatus 1 IF SERR()<>1 THEN @ShowError dlen = DPEEK($2EA) ' DVSTAT RESP$="-NONE-" if dlen if dlen > 255 then dlen = 255 @nread 1, &RESP$, dlen IF SERR()<>1 THEN @ShowError endif ENDPROC ' Shows an error and terminates PROC ShowError ? ""$9B$FD"ERROR - " ; SERR() ;""$FD @nclose 1 @ExitKey ENDPROC ' Get's a key and exists PROC ExitKey ? "PRESS ANY KEY"; REPEAT : UNTIL KEY() END ENDPROC ' Main program URI$ = "N:HTTPS://api.github.com/repos/dmsc/fastbasic/releases/latest"$9B ' Open URI ? "Opening:"$9B; URI$; @nopen 1, &URI$, $0C IF SERR()<>1 THEN @ShowError ' Switch to JSON mode @nchanmode 1, $0C, 1 IF SERR()<>1 THEN @ShowError ' And parse @njsonparse 1, $0C IF SERR()<>1 THEN @ShowError ' Query some properties: @query & "N:/name"$9B ? "Last FastBASIC version: "; RESP$ @query & "N:/published_at"$9B ? "Released at: "; RESP$ @query & "N:/created_at"$9B ? "Created at: "; RESP$ @nclose 1 ? "--------------------------" @ExitKey Second: Adding a statement to the native compiler. After you are sure you like the changes, you can add the new functionality to the native compiler. For this, you simply edit the main Makefile, adding to the variable "SYNTAX_FP" the new file: # Syntax files for floating-point version SYNTAX_FP=\ $(SYNTAX_INT)\ src/syntax/float.syn\ src/syntax/fujinet.syn\ You should add the files to the COMPILER_COMMON variable. After this, recompiling the code should make a new "FB.COM", 80 bytes bigger than before, with the "SIO" and "SERR()" added. See the attached ATR, including the modified IDE and the sample code as "FUJINET.BAS". Have Fun! fastbasic.atr 2 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 3, 2022 Author Share Posted November 3, 2022 3 hours ago, dmsc said: Hi! It is moderately easy, I tried to document it in https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md#extending-the-language . I will try to summarize bellow: First: Adding a statement to the cross compiler. This is the simplest part, as you don't need to recompile, only add new rules to the existing files. Looking at the repeating code, adding a "SIO" statement, similar to the existing "XIO", should simplify it a lot. In this case, the syntax for njsonquery could be something like: SIO $71, unit, $51, $80, addr+1, $1F, 256, aux1, 0 Now, to implement this, first we need to create a new target file, for example, named "fujinet.tgt": # FujiNet extended target include default syntax fujinet.syn This simply states that the fujinet target is copied from the default and adds new syntax definitions from the "fujinet.syn" file. Now, in the syntax folder, we create the file fujinet.syn with the contents: STATEMENT: "SIo" EXPR emit { TOK_NUM_POKE, &$300 } \ "," EXPR emit { TOK_NUM_POKE, &$301 } \ "," EXPR emit { TOK_NUM_POKE, &$302 } \ "," EXPR emit { TOK_NUM_POKE, &$303 } \ "," emit { TOK_NUM, &$304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ "," EXPR emit { TOK_NUM_POKE, &$306 } \ "," emit { TOK_NUM, &$308, TOK_SADDR } EXPR emit { TOK_DPOKE } \ "," EXPR emit { TOK_NUM_POKE, &$30A } \ "," EXPR emit { TOK_NUM_POKE, &$30B } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } INT_FUNCTIONS: "SErr()" emit { TOK_NUM, &$303, TOK_PEEK } This looks complicated, but it is simply adds two parsing rules: - A statement parsing rule that expects the word "SIO" (or "SI."), then 9 integer expressions, the "byte" expressions are simpler, as they get translated directly to a POKE to the given address, the "word" expressions need to use the "DPOKE" token, expecting the address in the SADDR register. Note that all literal 16 bit values need an "&" before. After all that preparation, the assembly routine at $E459 is called, and the returned value is simply discarded. - A function parsing rule, that expects "SERR()" (or "SE.") and simply returns the PEEK of address $303. With this changes, you can compile the test program using: fb -t:fujinet gitver2.bas This is the test program using the new "SIO" statement: ' FujiNET Sample: Gets last FastBASIC version from github. ' Open FujiNET SIO device PROC nopen unit addr aux1 SIO $71, unit, $4F, $80, addr+1, $1F, 256, aux1, 0 ENDPROC ' Close FujiNET SIO device PROC nclose unit SIO $71, unit, $43, $00, 0, $1F, 0, 0, 0 ENDPROC ' Read from FujiNET SIO device PROC nread unit addr rlen SIO $71, unit, $52, $40, addr+1, $1F, rlen, rlen, 0 POKE addr, rlen ENDPROC ' Get status from FujiNET SIO device PROC nstatus unit SIO $71, unit, $53, $40, $2EA, $1F, 4, 0, 0 ENDPROC ' Parse JSON internal buffer PROC njsonparse unit aux1 SIO $71, unit, $50, $00, 0, $1F, 0, aux1, 0 ENDPROC ' Query JSON from parsed PROC njsonquery unit aux1 addr SIO $71, unit, $51, $80, addr+1, $1F, 256, aux1, 0 ENDPROC ' Set channel mode PROC nchanmode unit aux1 mode SIO $71, unit, $FC, $00, 0, $1F, 0, aux1, mode ENDPROC ' Query one element from the JSON PROC query str @njsonquery 1, $0C, str IF SERR()<>1 THEN @ShowError @nstatus 1 IF SERR()<>1 THEN @ShowError dlen = DPEEK($2EA) ' DVSTAT RESP$="-NONE-" if dlen if dlen > 255 then dlen = 255 @nread 1, &RESP$, dlen IF SERR()<>1 THEN @ShowError endif ENDPROC ' Shows an error and terminates PROC ShowError ? ""$9B$FD"ERROR - " ; SERR() ;""$FD @nclose 1 @ExitKey ENDPROC ' Get's a key and exists PROC ExitKey ? "PRESS ANY KEY"; REPEAT : UNTIL KEY() END ENDPROC ' Main program URI$ = "N:HTTPS://api.github.com/repos/dmsc/fastbasic/releases/latest"$9B ' Open URI ? "Opening:"$9B; URI$; @nopen 1, &URI$, $0C IF SERR()<>1 THEN @ShowError ' Switch to JSON mode @nchanmode 1, $0C, 1 IF SERR()<>1 THEN @ShowError ' And parse @njsonparse 1, $0C IF SERR()<>1 THEN @ShowError ' Query some properties: @query & "N:/name"$9B ? "Last FastBASIC version: "; RESP$ @query & "N:/published_at"$9B ? "Released at: "; RESP$ @query & "N:/created_at"$9B ? "Created at: "; RESP$ @nclose 1 ? "--------------------------" @ExitKey Second: Adding a statement to the native compiler. After you are sure you like the changes, you can add the new functionality to the native compiler. For this, you simply edit the main Makefile, adding to the variable "SYNTAX_FP" the new file: # Syntax files for floating-point version SYNTAX_FP=\ $(SYNTAX_INT)\ src/syntax/float.syn\ src/syntax/fujinet.syn\ You should add the files to the COMPILER_COMMON variable. After this, recompiling the code should make a new "FB.COM", 80 bytes bigger than before, with the "SIO" and "SERR()" added. See the attached ATR, including the modified IDE and the sample code as "FUJINET.BAS". Have Fun! fastbasic.atr 179.64 kB · 0 downloads That is beautiful. -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 3, 2022 Author Share Posted November 3, 2022 20 hours ago, tschak909 said: That is beautiful. -Thom I think we should at the very least, put sio as a syntax in the a800 target. I will fold into my fork, test, and do a pull-request. Then I will experiment with adding NOPEN, NCLOSE, NREAD, NWRITE, and NSTATUS convenience commands. -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 4, 2022 Author Share Posted November 4, 2022 @dmsc FastBasic works just fine in the FujiNet NOS 2022-11-03 19-37-50.mp4 With this, I can make changes to the language on the PC side, compile, and immediately test the results on the Atari, no mounting of disk images. -Thom 2 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 5, 2022 Author Share Posted November 5, 2022 (edited) @dmsc Am currently debugging my first new statement, NOpen, it seems tokenizer errors really cause everything to go boom. STATEMENT: # nopen unit,daux1,daux2,addr_to_url "NOpen" EXPR emit { TOK_NUM_POKE, &$0301 } \ "," emit { TOK_NUM, &$030A, TOK_BYTE } EXPR emit { TOK_NUM_POKE } \ "," emit { TOK_NUM, &$030B, TOK_BYTE } EXPR emit { TOK_NUM_POKE } \ "," emit { TOK_NUM, &$0304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ emit { TOK_BYTE, &$71, TOK_NUM_POKE, &$0300 } \ emit { TOK_BYTE, &$4F, TOK_NUM_POKE, &$0302 } \ emit { TOK_BYTE, &$80, TOK_NUM_POKE, &$0303 } \ emit { TOK_BYTE, &$1F, TOK_NUM_POKE, &$0306 } \ emit { TOK_BYTE, &$00, TOK_NUM_POKE, &$0308 } \ emit { TOK_BYTE, &$01, TOK_NUM_POKE, &$0309 } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } Edited November 5, 2022 by tschak909 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 5, 2022 Author Share Posted November 5, 2022 wheee.... Compile src/compiler/synt-emit-asm.cc Compile src/compiler/synt-optimize.cc Compile src/compiler/synt-parser.cc Compile src/compiler/synt-preproc.cc Compile src/compiler/synt-pstate.cc Compile src/compiler/synt-sm.cc Compile src/compiler/synt-symlist.cc Compile src/compiler/synt-wlist.cc Compile src/compiler/syntp.cc Compile parser generator tool build/gen/syntp Creating FP parsing bytecode syntax: 123 possible tokens. syntax: 122 tables in the parser-table. syntax: inline table 'FP_FUNCS' into 'FP_T_EXPR'. syntax: optimizing table 'DATA_EXT_TYPE' empty, will delete. Compile src/compiler/atarifp.cc Compile src/compiler/codestat.cc Compile src/compiler/compile.cc Compile src/compiler/ifile.cc Compile src/compiler/looptype.cc Compile src/compiler/main.cc Compile src/compiler/os.cc Compile src/compiler/parser.cc Compile src/compiler/parser-actions.cc Compile src/compiler/peephole.cc Compile src/compiler/target.cc Compile src/compiler/vartype.cc Linking host compiler Compiling FP BASIC build/gen/cmdline-vers.bas BAS compile 'build/gen/cmdline-vers.bas' to 'build/gen/fp/cmdline-vers.asm' Compiling INT BASIC src/editor.bas BAS compile 'src/editor.bas' to 'build/gen/int/editor.asm' Creating INT parsing bytecode syntax: 97 possible tokens. syntax: 112 tables in the parser-table. syntax: optimizing table 'INT_FUNCTIONS' into 'T_EXPR'. syntax: optimizing table 'DATA_EXT_TYPE' empty, will delete. Compile CA65 Assembly FP src/actions.asm Assembly FP src/errors.asm Assembly FP src/memptr.asm Assembly FP src/parse.asm build/gen/fp/basic.asm(1918): Error: Symbol 'SM_EMIT_41' is undefined make: *** [rules.mak:204: build/obj/fp/parse.o] Error 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 5, 2022 Author Share Posted November 5, 2022 @dmsc is there a limit on the # of bytecodes that can be emit from a single instruction? -Thom Quote Link to comment Share on other sites More sharing options...
dmsc Posted November 5, 2022 Share Posted November 5, 2022 9 hours ago, tschak909 said: @dmsc is there a limit on the # of bytecodes that can be emit from a single instruction? -Thom Hi! Yes, there is a limit, but your problem is much simpler: after the "TOK_BYTE" you need to pass a byte, not a word, so you must delete the "&" symbol, with that the parser will need to emit a lot less bytes. Also, to optimize, there is a token TOK_0 that loads a zero an a TOK_1 that loads a 1. Have Fun! 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted November 5, 2022 Author Share Posted November 5, 2022 1 hour ago, dmsc said: Hi! Yes, there is a limit, but your problem is much simpler: after the "TOK_BYTE" you need to pass a byte, not a word, so you must delete the "&" symbol, with that the parser will need to emit a lot less bytes. Also, to optimize, there is a token TOK_0 that loads a zero an a TOK_1 that loads a 1. Have Fun! @dmsc could really use your help on the discord: https://discord.gg/7MfFTvD This works: # # FujiNet syntax additions by Thomas Cherryhomes # <thom dot cherryhomes at gmail dot com> # STATEMENT: "NOpen" EXPR emit { TOK_NUM_POKE, &$301 } \ "," EXPR emit { TOK_NUM_POKE, &$30A } \ "," EXPR emit { TOK_NUM_POKE, &$30B } \ "," emit { TOK_NUM, &$304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } This works: # # FujiNet syntax additions by Thomas Cherryhomes # <thom dot cherryhomes at gmail dot com> # STATEMENT: "NOpen" EXPR emit { TOK_NUM_POKE, &$301 } \ "," EXPR emit { TOK_NUM_POKE, &$30A } \ "," EXPR emit { TOK_NUM_POKE, &$30B } \ "," emit { TOK_NUM, &$304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ emit { TOK_NUM, &$4F80, TOK_NUM_POKE, &$302 } \ emit { TOK_BYTE, $1F, TOK_NUM_POKE, &$306 } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } THIS causes parser to puke: STATEMENT: "NOpen" EXPR emit { TOK_NUM_POKE, &$301 } \ "," EXPR emit { TOK_NUM_POKE, &$30A } \ "," EXPR emit { TOK_NUM_POKE, &$30B } \ "," emit { TOK_NUM, &$304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ emit { TOK_NUM, &$4F80, TOK_NUM_POKE, &$302 } \ emit { TOK_BYTE, $1F, TOK_NUM_POKE, &$306 } \ emit { TOK_NUM, &256, TOK_DPOKE, &$308 } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } ...with: thomc@TMA-2:~/Workspace/fastbasic$ make Creating FP parsing bytecode syntax: 123 possible tokens. syntax: 122 tables in the parser-table. syntax: inline table 'FP_FUNCS' into 'FP_T_EXPR'. syntax: optimizing table 'DATA_EXT_TYPE' empty, will delete. Assembly FP src/parse.asm build/gen/fp/basic.asm(1916): Error: Symbol 'SM_EMIT_22' is undefined make: *** [rules.mak:204: build/obj/fp/parse.o] Error 1 What is happening here? I seem to be emitting state machine values outside of the defined scope. Also, why do I see the inline table/optimizing table messages the moment I add any fujinet syntax? -Thom Quote Link to comment Share on other sites More sharing options...
dmsc Posted November 5, 2022 Share Posted November 5, 2022 Hi! 55 minutes ago, tschak909 said: @dmsc could really use your help on the discord: https://discord.gg/7MfFTvD Will tr to connect there. I replied last message from my phone, now I'm looking this closer. - Yes, the 6502 parser has a limit in the size of the "emit" blocks, it can output up to 16 bytes at once. - Yes, the parser generator has a bug, it joins all the emit blocks without looking at that limit. Las revision github (just pushed) fixes the problem, first it uses a higher limit of 28 bytes (this is the maximum with the current parsing bytecode) and it splits the emit blocks that are too big. 55 minutes ago, tschak909 said: THIS causes parser to puke: STATEMENT: "NOpen" EXPR emit { TOK_NUM_POKE, &$301 } \ "," EXPR emit { TOK_NUM_POKE, &$30A } \ "," EXPR emit { TOK_NUM_POKE, &$30B } \ "," emit { TOK_NUM, &$304, TOK_SADDR } EXPR emit { TOK_DPOKE } \ emit { TOK_NUM, &$4F80, TOK_NUM_POKE, &$302 } \ emit { TOK_BYTE, $1F, TOK_NUM_POKE, &$306 } \ emit { TOK_NUM, &256, TOK_DPOKE, &$308 } \ emit { TOK_NUM, &$E459, TOK_USR_ADDR, TOK_USR_CALL } ...with: thomc@TMA-2:~/Workspace/fastbasic$ make Creating FP parsing bytecode syntax: 123 possible tokens. syntax: 122 tables in the parser-table. syntax: inline table 'FP_FUNCS' into 'FP_T_EXPR'. syntax: optimizing table 'DATA_EXT_TYPE' empty, will delete. Assembly FP src/parse.asm build/gen/fp/basic.asm(1916): Error: Symbol 'SM_EMIT_22' is undefined make: *** [rules.mak:204: build/obj/fp/parse.o] Error 1 What is happening here? I seem to be emitting state machine values outside of the defined scope. The "SM_EMIT_22" bytecode was not possible for the 6502 parser, so it bails out. 55 minutes ago, tschak909 said: Also, why do I see the inline table/optimizing table messages the moment I add any fujinet syntax? Those messages should be always there. The parser generator tries to optimize the parsing tables, this is expected. Have Fun! 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.