SBASIC Programming

Anything QL Software or Programming Related.
Post Reply
User avatar
pjw
QL Wafer Drive
Posts: 1608
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

SBASIC Programming

Post by pjw »

Guys, spare a thought for us poor SMSQ/E users who prefer larger screen sizes than 512x256! It looks so dumb when programs, even those by modern programmers, all end up in the top left corner of the screen.

Trying out other people's programs that rely on channels #0, #1, #2 and end up messing up my display is not something I enjoy. Of course, I normally sandpit suspect programs in an SBASIC daughter job, so that saves a bit of annoyance.

But if you program in SBASIC, why not use something like this simple startup code:

Code: Select all

100 wsx% = 512: wsy% = 256: REMark My program's (fixed) window size
110 wox% = 0: woy% = 0:	    REMark Window origin
120 :
130 wc = FOPEN('con'):	    REMark Open a fresh output window
140 scrx% = SCR_XLIM(#wc): scry% = SCR_YLIM(#wc)
150 IF scrx% > wsx%: wox% = (scrx% - wsx%) / 2: REMark Center on screen
160 IF scry% > (wsy% + 20): woy% = 20:	REMark Leave room for button bar
179 WINDOW#wc; wsx%, wsy%, wox%, woy%
etc..
Remember, any output commands in that window would act relative to its window's origins, so you don't have to worry about that. For example, BLOCK#wc; bx, by, ox, oy will end up in the same place, relatively, as if the window had been 512 x 256 @ 0 x 0.

If your program doesn't have to have a fixed size you could for example let wsx% = scrx% and wsy% = scry% or any other size you choose. Display code would then have to be scaled accordingly. Take the Mandelbrot routines published by Steve recently:

Code: Select all

100 REMark MandelQdos_bas
110 WINDOW 512,256,0,0: PAPER 0: CLS
130 FOR d=0 TO 255
140  y0=(d-128)/128
150  FOR a=0 TO 511
160   x0=(a-256)/128: x=0: y=0
170    FOR i=1 TO 32
180     xt=x*x-y*y+x0: y=(2*x*y)+y0: x=xt
190     IF ((x*x+y*y)>4): EXIT i
200    END FOR i: BLOCK 1,1,a,d,(i MOD 8)
210  END FOR a: IF KEYROW(1)=8: EXIT d
220 END FOR d: PAUSE: PAUSE
On a larger screen it could easily be scaled. A few small changes does the trick:

Code: Select all

100 REMark MandelQdos_bas
102 ch=FOPEN("con")
104 scrx%=SCR_XLIM(#ch): scry%=SCR_YLIM(#ch)
106 x2%=scrx% DIV 2: y2%=scry% DIV 2
108 WINDOW#ch; scrx%,scry%,0,0: CLS#ch
112 FOR d=0 TO scry%-1
114  y0=(d-y2%)/y2%
116  FOR a=0 TO scrx%-1
118   x0=(a-x2%)/y2%: x=0: y=0
120    FOR i=1 TO 32
122     xt=x*x-y*y+x0: y=(2*x*y)+y0: x=xt
124     IF ((x*x+y*y)>4): EXIT i
126    END FOR i
128     BLOCK#ch;1,1,a,d,(i MOD 8)
130  END FOR a
132  IF KEYROW(1)=8: EXIT d
134 END FOR d
138 PAUSE#ch
This program will fill the display of a window of "any" size. It doesnt have to be the full screen. Just specify the size and position, as for example shown in the first code snippet.

If you have a larger screen but get an Out of Range error it is probably because the window it is being run in has already had its OUTLine set. Try it again in an SBASIC daughter job, ie type SBASIC<ENTER> in the main console and LRUN it from the daughter. Or use QD, one of the best programming text editors, and dispatch it directly from there with F10.

SBASIC programs can also be EXecuted like compiled or assembled jobs. (LRUN is for wimps! ;) ) If you had no luck RUNing it try that instead.

When you EXecute an SBASIC program you can make it so that it will accept parameters. Like a file name or something. No need for the user to fiddle the code or answer repeated INPUT questions each time. The program above has been modified below to take its parameters from the command line:

Code: Select all

100 REMark MandelQdos_bas
102 ch% = FOPEN("con")
104 if len(CMD$)  < 7 then
106  scrx% = SCR_XLIM(#ch%): scry% = SCR_YLIM(#ch%)
108  scox% = 0: scoy% = 0
110 else
112  Parse CMD$
114 endif
116 x2% = scrx% DIV 2: y2% = scry% DIV 2
118 WINDOW#ch%; scrx%, scry%, scox%, scoy%: CLS#ch%
120 :
122 t = date
124 FOR d% = 0 TO scry% - 1
126  y0 = (d% - y2%) / y2%
128  FOR a% = 0 TO scrx% - 1
130   x0 = (a% - x2%) / y2%
132   x = 0: y = 0
134    FOR i% = 1 TO 32
136     xx2 = x * x: yx2 = y * y
138     y = (2 * x * y) + y0
140     x = xx2 - yx2 + x0
142     IF ((xx2 + yx2) > 4): EXIT i%
144    END FOR i%
146    BLOCK#ch%; 1,1, a%, d%, (i% MOD 8)
148  END FOR a%
150  IF KEYROW(1) = 8: EXIT d%:	REMark ESC
152 END FOR d%
154 at#ch%; 2, scrx% div 6 - 5: print#ch%; date - t
156 BEEP 2000, 2
158 PAUSE#ch%; (date - t) * 25
160 QUIT
162 :
164 :
166 DEFine PROCedure Parse(cl$)
168 LOCal l%, p%, n%
170 l% = LEN(cl$)
172 scrx% = cl$
174 p% = ',' INSTR cl$
176 n% = p% + 1
178 scry% = cl$(n% TO l%)
180 p% = ',' INSTR cl$(n% TO l%)
182 n% = n% + p%
184 scox% = cl$(n% TO l%)
186 p% = ',' INSTR cl$(n% TO l%)
188 n% = n% + p%
190 scoy% = cl$(n% TO l%)
192 END DEFine Parse
194 :
196 :
To test it copy it to ram1_QMandel_bas

The program accepts four parameters: window size and origin, as in:

EX ram1_QMandel_bas;'300,200,50,20'

Values separated by comma with no spaces between. The parser, Parse, is very simple, so does not do any error checking for this example. If NO parameters are supplied the program takes up the whole screen.

To test it, I wrote this little dispatcher. I could have added some parameter parsing there too, but to keep it simple, youll have to make whatever changes in the code itself. It too is meant to be EXecuted, but you could just LRUN it or dispatch it directly from QD:

Code: Select all

100 REMark Tile multiple QMandles. Set nx, ny and fnm$
102 :
104 nx% = 2: ny% = 2
106 fnm$ = 'ram1_QMandel_bas'
108 :
110 sys_clnk = $C4: pt_xscrs = $F2: pt_yscrs = $F4
112 scrx% = PEEK_W(!sys_clnk! pt_xscrs): REMark Get screen size without
114 scry% = PEEK_W(!sys_clnk! pt_yscrs): REMark  a channel (PE only!)
116 :
118 FOR x% = 0 TO nx% - 1
120  FOR y% = 0 TO ny% - 1
122   xs% = scrx% DIV nx%
124   ys% = scry% DIV ny%
126   ox% = x% * xs%
128   oy% = y% * ys%
130   EX fnm$; xs% & ',' & ys% & ',' & ox% & ',' & oy%
132  END FOR y%
134 END FOR x%
136 IF JOBID: QUIT
138 :
140 :
Specify the number of "simultaneous" QMandel windows you want. As it stands there will be four: two next to each other above and two below. You could try nx% = 4 and ny% = 3,.. Once each program completes, it prints the seconds taken, and eventually it dies off again, so no need to quit them individually.

Lines 110 - 114 get the screen size directly from the driver, since no display channel is needed or wanted. This "trick" only works in SMSQ/E, without extra toolkits.

A couple of other things I like to see in the sort of programs we publish here, is an option to ESCape. Having to BREAK into a program to stop it can be a nuisance, especially if it leaves things dangling or in a mess. ESCape should lead to some form of clean termination that leaves the system much as it was. So, open channels should be closed, memory released, windows restored. BREAK is fine for debugging, but not for ordinary use. Like crashing your car into a tree every time you wanted to stop, before they invented breaks..

Another thing is programs that may take a long time to complete something. Sometimes it can be hard to know whether they are just in deep thought, or have crashed. A BEEP or a message would be useful here!

(I once uptated the OS on a Mac I had, via the internet. The machine appeared totally dead and unresponsive for 12 hours or so. Black screen, no messages, nothing to say what was going on. A wonder I didnt just pull the plug and complain! The next day, suddenly it sprang to life, updated! What utter idiots multi-trillion dollar companies can be! NOT an example to follow!)

Im not an expert programmer, but I try out a lot of programs to see whats going on, so I am, perhaps, a bit of an expert in what feels like "good paractice" to me.

I know there are many different setups, many different ways of doing things, many different ideas of do's and dont's. But things change, and so should we.


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
tofro
Font of All Knowledge
Posts: 3087
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: SBASIC Programming

Post by tofro »

Per,

agree that S*Basic programs should open their own window channels using FOPEN - and that it is in the programmer's best interest not to mess up carefully designed BASIC #0, #1, #2 windows tailored to their needs: All my BASIC programs that try to achieve at least some sophistication open their own, dedicated channels (and that mostly for my own good during development).

I don't really have an opinion on the need to center windows - If everyone did that, you'd have the same mess in the center of the screen that you now have in the top left (And I myself tend to use smaller and smaller display resolutions every year due to worse eyesight, so it really doesn't matter much anyways). Maybe you could work around this by putting your windows in some random place like some other OSs tend to. Ideally, really useful S*BASIC programs beyond a quick hack should incorporate a <CTRL>-F4-routine to move the window about (You don't need to mess with QPTR for that, at least not much). Unfortunately, there's no WMOV in SBASIC without a loaded toolkit, however. I think that is a serious omission.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Derek_Stewart
Font of All Knowledge
Posts: 4679
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: SBASIC Programming

Post by Derek_Stewart »

Hi,

I try not to use channels #0,#1,#2 in any programs I write, and open console or screen channels to suit the application.

I dislike programs that alter the standard QL windows, I serm to spend much time altering programs so they open their own windows.

This seems obvious to me as if I need ti access other hardware I open a new channel to it, instead of altering an existing open channel.

Back in the 80s,90s when Toolkit 2 was only available as a commerical product, the use of TK2 function to opened channels were never really adopted.

But now it is free, integrated in SMSQ/E and most disk interfaces, somwhy does one say:

OPEN #5;"con_512x256a0x0"

to find that the channel is alreay in use, surely the TK2 function:

ch=FOPEN("con_512x256a0x0")

is better as the operating system allocates the channel number, looks better.


Regards,

Derek
User avatar
pjw
QL Wafer Drive
Posts: 1608
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: SBASIC Programming

Post by pjw »

tofro wrote: Mon Dec 16, 2024 6:30 pm <>
I don't really have an opinion on the need to center windows - If everyone did that, you'd have the same mess in the center of the screen that you now have in the top left (And I myself tend to use smaller and smaller display resolutions every year due to worse eyesight, so it really doesn't matter much anyways). Maybe you could work around this by putting your windows in some random place like some other OSs tend to. Ideally, really useful S*BASIC programs beyond a quick hack should incorporate a <CTRL>-F4-routine to move the window about (You don't need to mess with QPTR for that, at least not much). Unfortunately, there's no WMOV in SBASIC without a loaded toolkit, however. I think that is a serious omission.
I agree! So howzabout this:

Code: Select all

100 rem     User settings
110 wsx% = 200: wsy% = 100:                         rem Window size
120 shd% = 5:                                       rem Shadow
130 :
140 rem     Init
150 sys_clnk = $C4:                                 rem Console linkage
160 pt_xpos  = $3C: pt_ypos = $3E:                  rem Pointer x/y
170 wox% = PEEK_W(! sys_clnk! pt_xpos):             rem Window origin =
180 woy% = PEEK_W(! sys_clnk! pt_ypos):             rem  pointer position
190 wc = FOPEN('con')
200 scrx% = SCR_XLIM(#wc): scry% = SCR_YLIM(#wc):   rem Screen x/y
210 :
220 rem     Adjust
230 IF (wox% + wsx% + shd%) > scrx%: wox% = scrx% - wsx% - shd%
240 IF (woy% + wsy% + shd%) > scry%: woy% = scry% - wsy% - shd%
250 WINDOW#wc; wsx%, wsy%, wox%, woy%
260 CLS#wc: BORDER#wc; 2, 233
270 OUTLN#wc; wsx%, wsy%, wox%, woy%, shd%, shd%
280 :
290 rem     Program
300 PRINT#wc; 'Window'! wsx%! 'x'! wsy%! '@'! wox%! 'x'! woy%
310 PAUSE#wc
All without any toolkits in SBASIC. Now we only need WMOV.


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
RalfR
QL Wafer Drive
Posts: 1178
Joined: Fri Jun 15, 2018 8:58 pm

Re: SBASIC Programming

Post by RalfR »

pjw wrote: Mon Dec 16, 2024 9:11 pm I agree! So howzabout this: .... All without any toolkits in SBASIC. Now we only need WMOV.
Works good :) . It's always a matter of preference, whether you prefer to have fixed or variable positions. If you use a Start-up program like Qascade, you alway stay at that place.

WMOV should be extracted from one of the EasyPTR toolkits. But some people always load it at BOOT.


7000 4E75
Derek_Stewart
Font of All Knowledge
Posts: 4679
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: SBASIC Programming

Post by Derek_Stewart »

Hi,

I agree with all this, I usually use SBASIC in SMSQ/E and Multibasic in Minerva and leave Job 0 alone.

It just means that the programme must open channels 0-2 its self.


Regards,

Derek
User avatar
pjw
QL Wafer Drive
Posts: 1608
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: SBASIC Programming

Post by pjw »

RalfR wrote: Tue Dec 17, 2024 5:34 am
pjw wrote: Mon Dec 16, 2024 9:11 pm I agree! So howzabout this: .... All without any toolkits in SBASIC. Now we only need WMOV.
Works good :) . It's always a matter of preference, whether you prefer to have fixed or variable positions. If you use a Start-up program like Qascade, you alway stay at that place.
These were just suggestions. There are many ways to slice an apple..
WMOV should be extracted from one of the EasyPTR toolkits. But some people always load it at BOOT.
Easier said than done! This is really a case of a banana connected to a gorilla, connected to the whole jungle! Although I have Albin's actual source code, I dont see any easy way of doing this. Probably less trouble writing something from scratch, although the ptrmen sources may offer some helpful hints..

In the mean time we have, as you say, ptrmen, which I load as a matter of course in all my setups. So Im unlikely to do anything about it, at least in the short term.

What might have been nice is a sort of "standard window" in Qmenu - or a la Qmenu, which you could use as you please, but which had the basic functions of Move, Resize, Sleep,, Wake, etc. Just enough to knock up some simple programs with a minimum of fuss.


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
RalfR
QL Wafer Drive
Posts: 1178
Joined: Fri Jun 15, 2018 8:58 pm

Re: SBASIC Programming

Post by RalfR »

pjw wrote: Wed Dec 18, 2024 6:48 pmWhat might have been nice is a sort of "standard window" in Qmenu - or a la Qmenu, which you could use as you please, but which had the basic functions of Move, Resize, Sleep,, Wake, etc. Just enough to knock up some simple programs with a minimum of fuss.
Oliver Fink has written such a program.....but for QPTR:

https://dilwyn.theqlforum.com/program/space.zip


7000 4E75
stevepoole
Aurora
Posts: 888
Joined: Mon Nov 24, 2014 2:03 pm

Re: SBASIC Programming

Post by stevepoole »

Hi Folks,

A very Merry Xmas to all,

( and especially to the person who wrote this seasonal program ) :
GladTidings.zip
(3.79 KiB) Downloaded 64 times


User avatar
ql_freak
Gold Card
Posts: 481
Joined: Sun Jan 18, 2015 1:29 am

Re: SBASIC Programming

Post by ql_freak »

Merry Christmas to all!

I'm not quite sure, if I understand fully about what this thread is. But I'm using (on QPC2) a batch program (SB without line numbers) to move a standard SBASIC (channels 0 to 2 with default sizes and colours) without loosing the loaded SBASIC program. I use it often, when using more than one SBASIC. The limits in the program are for a resolution of 1024x768. If you use higher/lower resolution, you should increase/decrease it.

Code: Select all

IF BASIC_INDEX%("x_%")<0:PRINT#0,"x_% (or y_%) not set! Aborting":END_CMD
IF BASIC_INDEX%("y_%")<0:PRINT#0,"y_% (or x_%) not set! Aborting":END_CMD
IF x_%<0 OR x_%>512:PRINT#0,"x_% must be in range 0..512!":END_CMD:REMark x%=x_%
IF y_%<0 OR y_%>512:Print#0,"y_% must be in range 0..512!":END_CMD:REMark y%=y_%
PRINT#0,"Reset SuperBASIC origin to "&x_%&", "&y_%&"?";
CURSEN#0:a_$=INKEY$(#0,-1):CURDIS#0
IF a_$<>'y'AND a_$<>'Y':PRINT#0,"User abort":END_CMD
PAPER#2,0:PAPER#1,0:PAPER#0,0
BORDER#2,0:BORDER#1,0:BORDER#0,0:CLS#2:CLS#1:CLS#0
WINDOW#2,256,202,x_%,y_%:WINDOW#1,256,202,x_%+256,y_%:WINDOW#0,512,54,x_%,y_%+202
CLS#0:WINDOW#0,512,54,x_%,y_%+202
BORDER#2,1,255:BORDER#1,1,255:BORDER#0,1,255
PAPER#2,7:PAPER#1,2:PAPER#0,0:CLS#2:CLS#1:CLS#0
END_CMD
Unfortunately can't remember from which Toolkit the BASIC_INDEX% is from (I assume Turbo Toolkit). This checks, if x_% and y_% (I hope no one uses those variable names in its SBASIC programs) are set before executing the batch program. END_CMD is from Turbo Toolkit (I always have installed this, as it is required for compiled Turbo programs). In addition I have set the following hotkey:

Code: Select all

ERT HOT_KEY("r","x_%=:y_%=:DO'resetSB_bat'"&FILL$(CHR$(192),21))
which results in:

Code: Select all

x_%=:y_%=:Do'resetSB_bat'
The cursor is at the first colon, so that you can easily set the top left origin.


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
Post Reply