The HiSoft BASIC useful routines and documentation guide by Paul Jones. Disk Compilation/Guide (c) Paul Jones 1997 Version 0.06 - 27/09/1997 Introduction --------------------------------------------------------------------------- My name's Paul Jones, and if any of you read the magazine Atari Computing, then you'll know I write the Basic BASIC! series of tutorials, teaching anyone how to program in HBASIC. I've been programming HBASIC for about three years now, and even though I've never released anything, I've been figuring out the odds and ends of the HiSoft BASIC package, and other things such as the VA protocol. I hope that this guide will provide you, the HiSoft BASIC user, the programming power you need to program a really useful application. For those of you who are new to HiSoft BASIC and/or GEM programming, I have included my BASIC tutorials (with pictures) to read - with these you could create your own GEM program with ease! Each section in this text guide is designed so that it can be updated with comments or source when the time comes - it's supposed to be a complete guide to HBASIC. How to use the guide --------------------------------------------------------------------------- The guide contains the latest information on how to use the language to it's most effective ability. It gives details on the features of HBASIC which are not documented fully, or not at all. Also included is routines on what the modern GEM applications use - iconify and BubbleGEM. Here is a full list of the subjects covered: The VA protocol Accessing BubbleGEM Iconify Libraries - GEMVDI note - library list - NetWorld - MODPLAY - WavePlay - OOPLIB - Writing your own libraries The Drag&Drop protocol Multitasking extras The latest GEMAES.BH file Tokenising Sprite mania Hex/Oct/Bin/Dec Blind dates Sources Shareware methods GEM globalisation Contact and contributing Contributers Copyright status Each guide section will always have an introduction of some sort, then some source code. It is then explained. If there are brackets "[" and "]", then the source code will be found on the disk with that name. The AV protocol --------------------------------------------------------------------------- By Paul Jones The AV protocol was invented for use in the GEMINI desktop, but now other desktops like Thing also support the "VA protocol", but what is the VA protocol? Well, as you guess by "protocol", it has something to do with communication between programs/accessories, and that's exactly what it is! The protocol allows your program to communicate with another and accessories too. It's also very simple to do and very practical. You must have been setting up CAB and wondering "What does 'Supports VA_START' mean?". For an accessory, say it loaded up MOD files to play when browsing WWW pages, it makes more sence to have it run as a background task so you could continue navigating instead of listening to the MOD for a while then continuing. So, CAB would have to send the acc a message telling it too play. Here's the protocol information: ------------------------------------------------------ | buffer[0] =| [Message-type] (e.g. VA_START) | | buffer[1] =| [Sender-ID](from appl_init()) | | buffer[2] =| 0 ('overlength') | | buffer[3] =| [Control-keys] (SENDKEY) | | | [Window-handle] (ACCWINDOPEN) | | | [Window-handle] (ACCWINDCLOSED) | | | [Window-handle] (DRAGACCWIND) | | | Pointer to path (Low) (STARTPROG) | | buffer[4] =| [Pressed key] (SENDKEY) | | |Pointer to path (High) (STARTPROG) | | | [Mouse X-Pos.] (DRAGACCWIND) | | | 0 (all others) | | buffer[5] =| Pointer to line (Low) (STARTPROG) | | | [Mouse Y-Pos.] (DRAGACCWIND) | | | 0 (all others) | | buffer[6] =|Pointer to line (High) (STARTPROG) | | | Pointer to path (Low) (DRAGACCWIND) | | | 0 (all others) | | buffer[7] =|Pointer to path (High) (DRAGACCWIND) | | | 0 (all others) | ------------------------------------------------------ In theory it's simple. (The above is taken from the ST-Guide information file). And yes, the above is designed for C purposes, but we can easyly translate this into HBASIC... [VASEND.BAS] REM $option y+,v+,u+,#,[ LIBRARY "GEMAES" DEFINT a-z a$=SPACE$(16) : a&=VARPTR(a$) c$="H:\MODS\INTRO.MOD"+CHR$(0) : c&=VARPTR(c$) i=appl_find("VASTART test 1") IF i=-1 THEN PRINT "Not here!" IF i-1 THEN POKEW a&,&H4711 POKEW a&+2,PEEKW(PEEKL(GB+4)+4) POKEW a&+4,0 POKEL a&+6,c& POKEW a&+10,0 appl_write i,16,a& END IF ...as the above. Lets go through it... (I'm assuming you read my tutorials to understand the basics at least...) a$=SPACE$(16) : a&=VARPTR(a$) Right, first to do a VA_START we need some space to use the appl_write command. This creates a string 16 bytes long, and the VARPTR finds the address of where this string is in memory. c$="H:\MODS\INTRO.MOD"+CHR$(0) : c&=VARPTR(c$) This is the message text we are going to send, and because the length of the string is unknown to the program we send it to, we need to add a CHR$(0) onto the end. Again, we find the address of this. i=appl_find("VASTART test 1") We find the program with the specified name (in this case my next accessory - next) IF i=-1 THEN PRINT "Not here!" IF i-1 THEN If it doesn't find it, there isn't much point of continuing... POKEW a&,&H4711 Put our first number into where the blank string is, the &H4711 is the code for VA_START, there are others (like the BubbleGEM commands). POKEW a&+2,PEEKW(PEEKL(GB+4)+4) Puts the next varible into the string, this time our application number. POKEW a&+4,0 A blank space. POKEL a&+6,c& Now we put the address of our string to send in the string, so the accessory/program receiving the message will know where the string is, as you cannot send strings - only numbers - so you CAN send the address of a string in memory (which is why we find the address of the string in the top section of the program) POKEW a&+10,0 Another blank. appl_write i,16,a& This is how the message is sent. appl_write sends data to an program/accessory running in memory, i is the number of the application here, the next number is how long the message is, and a& is the address of the data (which is why we found it out using VARPTR). END IF Finally end... This would send a message to the application called "VASTART test 1". I've programmed such an accessory with the source code below, with can receive the message we sent. NB: Any application which understands VA_START will be able to use the above program. [VAACC.BAS] DEFINT a-z REM $option y+,v+,u+,#,[,] REM $option j10 LIBRARY "GEMAES" REM $include gemaes.bh CONST va_start=&H4711 COMMON SHARED junk SUB got_vastart STATIC mess&,id,addr&,addr2&,a,file$,b SHARED mess(1) file$="" mess&=VARPTR(mess(0)) id=SPEEKW(mess&+2) addr&=SPEEKL(mess&+6) DO a=PEEKB (addr&) IF a0 THEN file$=file$+CHR$(a) INCR addr& LOOP UNTIL a=0 b=form_alert (1,"[1][ From id:"+STR$(id)+" file name: | "+file$+" ][ Ok ]") END SUB SUB do_message STATIC cur_front,MessageType,title,item SHARED exit_item,Finished_Flag,Mess(1),AlreadyOpen MessageType=Mess(0) junk=wind_get(Mess(3),WF_TOP,cur_front,junk,junk,junk) SELECT CASE MessageType CASE AC_OPEN: junk=form_alert (1,"[1][ VA_START test 1 accessory by | Paul Jones to test VA_START ][ Ok ]") CASE VA_START CALL got_vastart END SELECT END SUB SUB StartAccessory(daname$) SHARED WindX,WindY,WindW,WindH SHARED Mess(1) STATIC id,mpos DIM Mess(16) id=PEEKW(PEEKL(GB+4)+4) mpos=menu_register(id,daname$) junk=wind_get(0,WF_WORKXYWH,WindX,WindY,WindW,WindH) DO evnt_mesag VARPTR(mess(0)) do_message LOOP END SUB StartAccessory (" VA_START test 1") Again, lets go through it. REM $option j10 Tells HBASIC that we're making an accessory and to reserve 10K for it to use. Anything after j indicates the number of K to reserve. CONST va_start=&H4711 Define the message number of VA_START. There are other message numbers too. SUB got_vastart STATIC mess&,id,addr&,addr2&,a,file$,b SHARED mess(1) file$="" mess&=VARPTR(mess(0)) id=SPEEKW(mess&+2) addr&=SPEEKL(mess&+6) DO a=PEEKB (addr&) IF a0 THEN file$=file$+CHR$(a) INCR addr& LOOP UNTIL a=0 b=form_alert (1,"[1][ From id:"+STR$(id)+" file name: | "+file$+" ][ Ok ]") END SUB Biggy eh? Pretty simple, mess& is the address of where the data is. All we're doing is taking apart the information the program/accessory sent us. id will contain the identification number of the program that sent us this data, and addr& is the address of where the string data is. The DO routine adds all the characters that are not CHR$(0) to file$, so we get the string, excluding that CHR$(0). Finally we bring up an alert box which says which application number sent it us (0 for programs running in TOS), and the file name, which you could do anything with, play a MOD file, display as text, etc. SUB do_message STATIC cur_front,MessageType,title,item SHARED exit_item,Finished_Flag,Mess(1),AlreadyOpen MessageType=Mess(0) junk=wind_get(Mess(3),WF_TOP,cur_front,junk,junk,junk) SELECT CASE MessageType CASE AC_OPEN: junk=form_alert (1,"[1][ VA_START test 1 accessory by | Paul Jones to test VA_START ][ Ok ]") CASE VA_START CALL got_vastart END SELECT END SUB Finds out which message has been sent to us. As you can see, there is more than just VA_START. If it is a VA_START, then the goes to the got_vastart SUB above. If the accessory is clicked on, the message sent is AC_OPEN, and if that's that case, we have a nice alert box telling the user about the accessory. SUB StartAccessory(daname$) SHARED WindX,WindY,WindW,WindH SHARED Mess(1) STATIC id,mpos DIM Mess(16) id=PEEKW(PEEKL(GB+4)+4) mpos=menu_register(id,daname$) junk=wind_get(0,WF_WORKXYWH,WindX,WindY,WindW,WindH) DO evnt_mesag VARPTR(mess(0)) do_message LOOP END SUB This is the main accessory bit. This is describe is full in the accessory section. StartAccessory (" VA_START test 1") And again. You can also send application specific messages to applications ie BubbleGEM. See "Accessing BubbleGEM" for more info. Note with sending VA's, you can actually send ST-guide messages to display help files. The format is: FILENAME section eg C:\MYDIR\HELPME.HYP maindialog Accessing BubbleGEM --------------------------------------------------------------------------- By Paul Jones On the Reader Disk to Atari Computing issue 5 is a copy of BubbleGEM. The main purpose of it is to bring up a speech bubble displaying help when you click on the right mouse button of a button in a formwindow to see what it will do if you click on that particular button. And yes, you too can use it in HBASIC! It works mostly by the same method as above: /* BUBBLEGEM_SHOW - Information: * msg[0] $BABB * msg[1] ap_id * msg[2] 0 * msg[3] Mouse X * msg[4] Mouse Y * msg[5/6] Pointer to nullterminated string in globalen * Memory * msg[7] 0 */ Again, this is in C syntax but we can convert it. Instead of our VA_START code (4711 in hex), we use BABB in hex. Looking at the above information, you can see it's much the same information is needed as in a VA_START. All that's different is the Mouse X and Mouse Y. [SENDBUB.BAS] DEFINT a-x LIBRARY "GEMAES" c$=SPACE$(16) : c&=VARPTR(c$) ad$="This is a demo of how to use BubbleGEM. As you can see it brings a bubble up on the screen!" ad$=ad$+" This is useful for help functions in programs, but only if the dialog is non-modal. The" ad$=ad$+" call to access it is a combination of things with a appl_write at the end"+CHR$(0) : ad&=VARPTR(ad$) IF LEN(ad$)>255 THEN STOP -1 i=appl_find("BUBBLE ") IF i=-1 THEN BEEP : STOP-1 POKEW c&,&HBABB POKEW c&+2,PEEKW(PEEKL(GB+4)+4) POKEW c&+4,0 POKEW c&+6,MOUSE(0) POKEW c&+8,MOUSE(1) POKEL c&+10,ad& POKEW c&+14,0 appl_write i,16,c& c$=SPACE$(16) : c&=VARPTR(c$) ad$="This is a demo of how to use BubbleGEM. As you can see it brings a bubble up on the screen!" ad$=ad$+" This is useful for help functions in programs, but only if the dialog is non-modal. The" ad$=ad$+" call to access it is a combination of things with a appl_write at the end"+CHR$(0) : ad&=VARPTR(ad$) Like in the VA_START code we reserve some space, and create our string to be "bubbled" IF LEN(ad$)>255 THEN STOP -1 BubbleGEM can only handle strings this than 255 characters long. i=appl_find("BUBBLE ") IF i=-1 THEN BEEP : STOP-1 Find the application number BubbleGEM is running on. It it isn't there, quit. POKEW c&,&HBABB POKEW c&+2,PEEKW(PEEKL(GB+4)+4) POKEW c&+4,0 POKEW c&+6,MOUSE(0) POKEW c&+8,MOUSE(1) POKEL c&+10,ad& POKEW c&+14,0 Much the same as the VA_START code. Notice MOUSE(0) and MOUSE(1)? MOUSE(0) will return the current X position of the mouse on screen, and MOUSE(1) will do the same for the Y. appl_write i,16,c& This is send our message to BubbleGEM, and will bring up a bubble containing the text at the top of the program, at the co-ordinates of X,Y. Iconify --------------------------------------------------------------------------- By Paul Jones With the AES 4.1, and with programs which support iconifing, a little triangle button appears in the top right hand corner. If you press this button, the window is shrinked down to the bottom of the screen, which is useful is you have lots of windows open on screen. Iconifing in HBASIC is pretty easy, it requires the new GEMAES.BH file (found elsewhere in this document), and that you are using windows/formwindows instead of dialogs. First, you must find your routine which get system messages and deals with them (if you're using the HGT's, this is in WINDOW.BAS, sub WindowMessage). You then need to add: CASE WM_ICONIFY junk=wind_set (mess(3),WF_ICONIFY,mess(4),mess(5),mess(6),mess(7)) myicon(mess(3))=1 CASE WM_UNICONIFY junk=wind_set (mess(3),WF_UNICONIFY,mess(4),mess(5),mess(6),mess(7)) myicon(mess(3))=0 Note: myicon() must be defined in the formwindow initialisation code (found in FORMWIND.BAS). You then need to add another section to your redraw routine, if myicon(handle)=1 then the window is iconified and the icon should be redrawn. I use a sub program called ProcessUserIconify: SUB ProcessUserIconify (x,y,w,h) STATIC logo&,xout,yout,wout,hout junk=rsrc_gaddr (0,iconpic,logo&) ' iconpic is the tree to your icon, it should be 32x32. See ICON.RSC ' for an example. SelectTreeAddr logo& junk=wind_calc (1,9,x,y,w,h,xout,yout,wout,hout) DECR xout DECR yout DECR wout DECR hout setob_x 0,xout setob_y 0,yout setob_width 0,wout setob_height 0,hout junk=objc_draw (logo&,0,10,xout,yout,wout,hout) END SUB If myicon(handle)=0 then the redraw should be treated to the formwindow/window. Windows should have &H4000 added onto their windowcomp status's. What happens is that the AES tells us that the user has clicked on our window and wants it iconified. Then we give a message back saying to make it small, as you may have noticed, this is the same sort of thing whih happens for other window messages! Libraries --------------------------------------------------------------------------- By Paul Jones - GEMVDI note ------------------------------------------------------------------------ You might have noticed that most VDI commands are not in the GEMVDI library. The HBASIC manual lists some of them, but there are plently more. These are in the FALCON lib. If you have the Atari Compedium, you will see these commands. There are just too many to list in this short space. - library lists ------------------------------------------------------------------------ Please note all libraries here (unless stated) are included on the disk. New libraries are created by a third party to enhance HiSoft BASIC. They are written in machine code and can be accessed in HBASIC by "library ", where is the library you wish you use. Here is a list of them, and what they do: - NetWorld --------------------------------------------------------------------- NetWorld is a library so you can use STiK (the ST internet Kit) to connect to the internet. It is a simple library, with an include file to rid yourself of tedious functions like getting C strings, sending data, and connecting to a host etc. Needs: HiSoft BASIC (either major version), a modem and an internet account. Achievements: With it you can create your own internet clients! By: Paul Jones, email paulat.jones@zetnet.co.uk - MODPLAY --------------------------------------------------------------------- MODPLAY lets you play MOD files via the DSP on the Falcon on interupt. This means only 12% processor time is used and it will run in the background without you having do to anything! Needs: HiSoft BASIC (either major version), a Falcon with DSP, MOD files! Achievements: Create your own MOD file player. By: MOD player routines by bITmASTER of BSW, original library code by Graig Graham, new version by Paul Jones. - WavePlay --------------------------------------------------------------------- WavePlay lets you use System Audio Manager (SAM), with KP SACK to have your own program sound effects. The user chooses a sound for a certain event, and your program tells SAM to play it. Simple. Needs: TOS 2.xx or greater and DMA sound. Achievements: SAM is quoted as having unleashed potential. Your programs would be more in the "multimedia" style if you used SAM. By: WavePlay lib. is by Paul Jones. KP SACK is by Kosmik Phish Productions and SAM 1.3 is by Scott Sanders at Atari Corp with bugs fixed by KPP. - OOPLIB --------------------------------------------------------------------- Object Orientated Programming LIBrary is for programming where the emphasis is on objects. OOP is implemented in C and is claimed to be "missing" from HBASIC. Because of the use of objects, it is ideal for Graphical User Interface programs. By Graig Graham. - Writing your own libraries ------------------------------------------------------------------------ If you wish to write your own libraries, you'll need to know machine code. An example library is included. Libraries need to be linkable (which means you need to write them in a Devpac above v1.2). A library structure: opt p+,l+,c+ INCLUDE LIBRARY.H library LIBRARYNAME xref get_string external references * get_string inputs: * a0.l the address of the string * outputs: * d1.l the address of string * d4.l the length of the string xref get_array * get_array inputs: * a0.l the array desciptor * d0.w number of dimensions the * array should have. * outputs: * a2.l the address of the first * array element * d4.l total length in bytes of * array xref make_string * make_string inputs: * a0.l the string descriptor of * a string value * a1.l the address of your copy * of the string * d4.l the length of the string * outputs: * nothing xref.l gl_scratch this is referenced off global! xdef routine1 xdef routine2 fn_int vlng,vlng,int * routine1 takes in a long,long,int, * returns a int fn_int_np * routine2 returns a int - no * parameters. Note that anything with * a "_np" means no paramters - an * addition to the library.h file by * Paul Jones option 'uv' libstart routine1 * code here move.l 4(sp),a0 *Get the long, located at 4(sp). At (sp) is the return address. Each *parameter is added onto the stack. move.l 8(sp),a1 move.w 12(sp),a2 move.w #1,tos *anything which is put into tos (really d6) is returned. .w for a int, .l for a long. rts routine2 * code here rts Code must be position independant. The following types are available: subdef a subprogram subdef_np same as above with no parameters fn_int function which returns a 16-bit integer fn_int_np same as above with no parameters fn_lng function which returns a 32-bit integer fn_lng_np same as above with no parameters fn_sng function which returns a single precision number fn_sng_np same as above with no parameters fn_dbl function which returns a double precision number fn_dbl_np same as above with no parameters There is also types of parameters: int a 16-bit interger lng a 32-bit long integer sng a 32-bit FFP single-precision value dbl a 64-bit IEEE double-precision value str a string value aint an array of ints alng an array of lngs asng an array of sngs adbl an array of dbls astr an array of strings vint varptr(int-variable) vlng varptr(lng-variable) vsng varptr(sng-variable) vdbl varptr(dbl-variable) vstr varptr(string-variable) The Drag&Drop protocol --------------------------------------------------------------------------- Example by Michael Wensley In MultiTOS it is possible for you to create a program which when the user drags a file onto your window, it can load it. You can also send drag&drop messages. Go into the DRAGDROP folder, there is DRAGDROP.BAS. This program was created by Michael Wensley. It shows you a simple GEM program and how to get a drag&drop message (he hasn't figured out how to send one yet). Multitasking extras --------------------------------------------------------------------------- By Paul Jones In a multitasking system, the user wishes to have such features as iconify (defined above), drag&drop and have the program display it's real name in the desk menu. [MULTITAS.BAS] ' The multitasking library source by Paul Jones 1997 ' This code may be included in your own programs for free FUNCTION aesversion aesversion=PEEKW(PEEKL(GB+4)) END FUNCTION FUNCTION max_progs max_progs=PEEKW(PEEKL(GB+4)+ap_count) END FUNCTION Uses the GB array to check the maximum number of programs. Multitasking systems return -1. FUNCTION appl_id appl_id=PEEKW(PEEKL(GB+4)+ap_id) END FUNCTION This finds out what our current id number is. SUB Multitask_name (name$) STATIC mpos IF max_progs=-1 OR aesversion>=&H410 THEN mpos=menu_register(appl_id,name$) END SUB This subprogram checks to see if the system is multitasking, and if it is it sets the name. This can be included in your programs and save a bit of time (it also makes your program look better in the long run with extra goodies). You also might have noticed that some programs (like KP SACK) can automaticlly shutdown when you want to change resolution. Programs which don't support this feature have to be closed down manually! To make your programs AP_TERM compatible: IF appl_find("AGI?") OR aes_version>= &H410 THEN appl_getinfo_valid=TRUE IF appl_getinfo_valid THEN junk=appl_getinfo(10,max_shellwrite,dummy, dummy, dummy) junk=appl_getinfo(12,ap_termsent, dummy, dummy, dummy) if max_shellwrite>=9 AND ap_termsent!=0 THEN set_apterm=TRUE; END IF IF aes_version>= &H330 OR set_apterm THEN shel_write(9,1,0,0,0) END IF This above is converted from C. I'm not sure if this works or not, so use at your own risk! Thanks to Anthony Jacques for the C code. The latest GEMAES.BH file ------------------------------------------------------------------------ Compiled by Paul Jones/Michael Wensley [GEMAES.BH] ' GEMAES.BH ' constant file for HiSoft BASIC ' use defint a-z and option u+ 'offsets in bytes for the global array CONST ap_version=0,ap_count=2,ap_id=4,ap_private=6,ap_ptree=10 ' constants for message types CONST mn_selected=10,wm_redraw=20,wm_topped=21,wm_closed=22,wm_fulled=23 CONST wm_arrowed=24,wm_hslid=25,wm_vslid=26,wm_sized=27,wm_moved=28 CONST wm_untopped=30,wm_ontop=31 CONST ac_open=40,ac_close=41 CONST ap_term=50,ap_aptfail=51,ap_reschg=57 CONST shut_completed=60,resch_completed=61,ap_dragdrop=63,sh_wdraw=72 CONST ch_exit=80 'offsets in bytes for OBJECT structure CONST ob_next=0,ob_head=2,ob_tail=4,ob_type=6,ob_flags=8,ob_state=10 CONST ob_spec=12,ob_x=16,ob_y=18,ob_width=20,ob_height=22 'offsets in bytes for TEDINFO structure CONST te_ptext=0,te_ptmplt=4,te_pvalid=8,te_font=12,te_just=16 CONST te_color=18,te_thickness=22,te_txtlen=24,te_tmplen=26 'offsets in bytes for ICONBLK structure CONST ib_pmask=0,ib_pdata=4,ib_ptext=8,ib_char=12,ib_xchar=14,ib_ychar=16 CONST ib_xicon=18,ib_yicon=20,ib_wicon=22,ib_hicon=24,ib_xtext=26 CONST ib_ytext=28,ib_wtext=30,ib_htext=32 'offsets in bytes for BITBLK structure CONST bi_pdata=0,bi_wb=4,bi_hl=6,bi_x=8,bi_y=10,bi_color=12 'offsets in bytes for APPLBLK structure CONST ab_code=0,ab_parm=4 'offsets in bytes for PARMBLK strucure CONST pb_tree=0,pb_obj=4,pb_prevstate=6,pb_currstate=8,pb_x=10,pb_y=12 CONST pb_w=14,pb_h=16,pb_xc=18,pb_yc=20,pb_wc=22,pb_hc=24,pb_parm=26 'OBJECT Types CONST G_BOX=20,G_TEXT=21,G_BOXTEXT=22,G_IMAGE=23,G_PROGDEF=24,G_IBOX=25 CONST G_BUTTON=26,G_BOXCHAR=27,G_STRING=28,G_FTEXT=29,G_FBOXTEXT=30 CONST G_ICON=31,G_TITLE=32 'Object flag masks CONST mask_none=0,mask_selectable=1,mask_default=2,mask_exit=4 CONST mask_editable=8,mask_rbutton=16,mask_lastob=32,mask_touchexit=64 CONST mask_hidetree=128,mask_indirect=256,mask_3d=&h600 ' 3D mask values CONST fl3dind=&h200,fl3Dback=&h400,fl3dact=&h600 'Object state masks CONST mask_normal=0,mask_selected=1,mask_crossed=2,mask_checked=4 CONST mask_disabled=8,mask_outlined=16,mask_shadowed=32 ' constants for wind_create bits CONST win_name=1,win_close=2,win_full=4,win_move=8,win_info=16,win_size=32 CONST win_uparrow=64,win_dnarrow=128,win_vslide=256,win_lfarrow=512 CONST win_rtarrow=1024,win_hslide=2048,win_all=&hfff 'constants for wind get and set CONST wf_name=2,wf_info=3,wf_workxywh=4,wf_currxywh=5,wf_prevxywh=6 CONST wf_fullxywh=7,wf_hslide=8,wf_vslide=9,wf_top=10,wf_firstxywh=11 CONST wf_nextxywh=12,wf_newdesk=14,wf_hslize=15 CONST wf_vslsize=16,wf_screen=17,wf_color=18,wf_dcolor=19,wf_owner=20 CONST wf_bevent=24,wf_bottom=25 'wind_update constants CONST END_UPDATE=0,BEG_UPDATE=1,END_MCTRL=2,BEG_MCTRL=3 ' message types for evnt_multi CONST mu_keybd=1,mu_button=2,mu_m1=4,mu_m2=8,mu_mesag=16,mu_timer=32 CONST type_tree=0,type_object=1,type_string=5,ob_sizeof=24 CONST FMD_START=0, FMD_GROW=1, FMD_SHRINK=2, FMD_FINISH=3 'objc_sysvar values CONST lk3dind=1,lk3dact=2,indbutcol=3,actbutcol=4,backgrcol=5,ad3dvalue=6 ' end of GEMAES.BH ' additional bits by Paul CONST AP_DRAGDROP=63, DD_OK=0, DD_NAK=1, DD_EXT=2, DD_LEN=3, DD_TRASH=4 CONST DD_PRINTER=5, DD_CLIPBOARD=6 CONST WM_ICONIFY=34, WF_ICONIFY=26, WF_UNICONIFY=27, WF_UNICONIFYXYWH=28 CONST WM_UNICONIFY=35, WM_ALLICONIFY=36 Tokenising ------------------------------------------------------------------------ By Paul Jones If you include files a lot, which are hardly ever edited, you might think about "tokenising" them. This means that the files are compiled into a file, and that file is included with the code. To tokenise, create a new blank file. Then cut and paste your listed include files to this file. Save the file. Then make sure the compilation path and include file options in the dialog box are set to nothing. Click on OK, then the same menu, select "dump tokins". These will now be compiled and saved to disk. In your main program, when compiling, enter the name of the tokenised file in the tokenised path. If you later mess around with your lib files (create another one) and try to use tokens, you may get the error "internal error BADRT around line ", in this case you need to re-tokenise your files. In short, tokenised files can save you a lot of compiling time. Sprite mania --------------------------------------------------------------------------- By Paul Jones (example by Michael Wensley) You might like to create a game with HBASIC, and what a good excuse it is to have a play! ;-) You can create sprites in a resource editor (such as RSM or Interface) and then use them in your programs! The advantage is that GEM will automatically find how many colours your system has and display an icon nearest to that number of colours. WERCS has trouble with colours icons, and will crash (and even trash your RSC file!) if you try to display one in it! If you go into the SPRITE folder, you will find the source code to SPRITE.BAS, a little "game" where a icon follows the mouse pointer around - an example of a GEM game. At the moment I'm thinking about writing a game library for HBASIC, which will include things such as TrueColour sprite displaying routines. Another by Michael Wensley. Hex/Oct/Bin/Dec --------------------------------------------------------------------------- By Paul Jones We all know what Decimal is - we use it everyday. It is simply a plain number, such as 2. However, programmers, when using large numbers, such as memory locations need to use a better system of numbering. A large number such as 652212 is represented in Hexdecimal as 9F3B4. As you can see, the second number is smaller - it has a power of 16. Octal has has power of 8. Binary is a number system which is used by the computer - 1s and 0s. Here is an example from 0-20 in each form: ------------------------------------------------------------------ | x | Decimal (x) | Hexdecimal (&Hx) | Octal (&Ox) | Binary (&Bx) | ------------------------------------------------------------------ | 00 | 00 | 00 | 00 | 000000 | | 01 | 01 | 01 | 01 | 000001 | | 02 | 02 | 02 | 02 | 000010 | | 03 | 03 | 03 | 03 | 000011 | | 04 | 04 | 04 | 04 | 000100 | | 05 | 05 | 05 | 05 | 000101 | | 06 | 06 | 06 | 06 | 000110 | | 07 | 07 | 07 | 07 | 000111 | | 08 | 08 | 08 | 10 | 001000 | | 09 | 09 | 09 | 11 | 001001 | | 10 | 10 | 0A | 12 | 001010 | | 11 | 11 | 0B | 13 | 001011 | | 12 | 12 | 0C | 14 | 001100 | | 13 | 13 | 0D | 15 | 001101 | | 14 | 14 | 0E | 16 | 001110 | | 15 | 15 | 0F | 17 | 001111 | | 16 | 16 | 10 | 20 | 010000 | | 17 | 17 | 11 | 21 | 010001 | | 18 | 18 | 12 | 22 | 010010 | | 19 | 19 | 13 | 23 | 010011 | | 20 | 20 | 14 | 24 | 010100 | ------------------------------------------------------------------ A number with &H before it represents a Hexdecimal number, &O for Octal and &B for binary. A Decimal number does not need a header. Use HEX$(), BIN$(), VAL() and OCT$() for converted to Hexdecimal, Binary, Decimal and Octal respectivly. Blind dates --------------------------------------------------------------------------- By Paul Jones Over the past couple of years, there has been a lot of confusion over the millineum problem: what happens to your computer when 2000 comes up as the year? For the PC, because most of them use 19xx, where xx is stored in memory, when this goes from 99 to 00, the year will be displayed as 1900!! The Atari on the other hand uses an offset method, starting from 1980. Ie a value of 17 returned from the date function is really 1997. Using this method, it is possible to go to 2100. HiSoft BASIC has a bug in it's inbuilt date$ function, the year 2001 is returned as 20:1... what's going on? Well, in ASCII the number table goes like 0123456789:;<... change the date to 2021 then display the date the HBASIC. Looks horrid doesn't it? Well, this routine gets the date from the GEMDOS function tgetdate% and works perfectly. It also means that you're not resticted to the default American date format!! [DATE.BAS] LIBRARY "gemdos" DEFINT a-z a$=BIN$(tgetdate) PRINT "HBASIC date:"+DATE$ PRINT "The REAL date is:" day=VAL("&B"+MID$(a$,LEN(a$)-4,5)) month=VAL("&B"+MID$(a$,LEN(a$)-8,4)) l=LEN(a$)-9 year=VAL("&B"+MID$(a$,1,l)) PRINT day;"/";month;"/";1980+year The value returned by tgetdate% is in binary, so first has to be converted, then a number of bits represent data: Bits Function 0-4 Day 1-31 5-8 Month 1-12 9-15 Year 0-119 since 1980 The binary value need to be reversed, you'll find the last 5 bytes the day, the 4 before that are the month and the rest are the year. Sources --------------------------------------------------------------------------- Compiled by Paul Jones These are found in the SOURCE folder: COLDIS .BAS - Displays a "colour circle" displaying the system colours. By Paul Jones. COLOR .BAS - Starts off as a white screen and fades down to black using the VDI, useful for a screen saver. By Paul Jones. FSFIRST .BAS - Shows you how to use the GEMDOS command FSFIRST to retrive an entire directory. By Paul Jones. MENUTEST.BAS - With AES v3.3 you can create sub directories in menus, this gives an example of how to do it. By Paul Jones. MULTI .BAS - Source code to MOD file player (using MODPLAY lib). Supports VA start. By Paul Jones. SPEEDO .BAS - An example of how to use SpeedoGDOS to display vector fonts, only works when Speedo/NVDI is installed! By Paul Jones. TPP .BAS - The Power Protector source code, a program designed for encryption of files. Buggy, but shows you how it works ;-) By Paul Jones 1995. TRIS .BAS - The Real Inteligent System. If you've ever used DOS, then you'll know how boring the command lines are. Well, TRIS was designed so that you could type in "TRIS, give me a directory listing of drive D, in the folder PJCO with the extension .TXT", and it works! I haven't done anything to it in a while... anyone willing to continue it? By Paul Jones 1996. WWW_CODE.BAS - This code comes from the NeST (NEtwork ST) and is supposed to be the beginning source code to a HTML viewer! XOR .BAS - An example of how to encode strings with passwords, by Paul Jones. GIF89A .BAS - I (Paul Jones) created when I was asked by Matthew Bacon for his Web.Wizard to get the x and y size of a GIF file... and here's the result! Shareware methods --------------------------------------------------------------------------- By Paul Jones Shareware is form of release where the programmer retains the copyright to the program, and the program maybe freely distributed like freeware. However, the shareware aspect means that after a certain time of use the user must give the programmer some form of payment (other variations of this are "chocolateware", "postcardware", "contactware" and "emailmailware" but are all related in that they want the programmer to shown some sign of reaction to their shareware notice). Some shareware programs have no features disabled, so the user can try out all of the program and "register" if they use the program regualarly. However, we are all very lazy, and Mr. Average (or Mrs.) wouldn't pay money for what they didn't really have too... So how do we get around this problem? Well, the common solution is to install a registrion system, where some areas of the program are disabled and when the user registers the program with the user, the programmer gives them a "key" which they type into the program and the actives the before disabled features. Others will have time delays or a registration box popping up ever so often. An example of this is Everest. You might have heard of "hackers". These people will try to work something out to change the program without the programmers permission to their own benefit. Some (in the case of games) might try to find a cheat in a program which is imbedded into the compiled game, or in the case of application software try to find your "key" in the program which will be checked against what the user types in to verfify that the program has be registered. Because of the way programs are compiled, such things as string can be seen in programs if you use a Disk Editor, such as Knife or DADE. A hacker can go through your program and try to find any strings in the compiled version with a DE and try typing in these for keys. For example, if I wrote in my program: dummy$="Hello there hacker!" A hacker with a Disk Editor would see your little message as some garbage then "Hello there hacker!" without the speech marks! ;-). You could encrypt your password in the program. The hacker then wouldn't be able to tell the difference between the password (which would now look like a load of symbols), and the compiled program. So, what could your program do be persuade the user to register. Well, the most obvious is not to supply some features, or disable some. For example for a printing utility only allow the user to print out two documents per program load. On startup you could display a register dialog (like Everest), or after a certain display a "time delay" - a dialog box showing for a certain amount of time so that the user can't do anything else until this box is gone. Of course, when the user registers, these "features" go away :-). The idea is to restict the program as much as possible, but making sure the user can try out your software. This might (on the other hand) mean that the user deletes your program all together because he/she was getting annoyed of all those register boxes! Back to the drawing board!! :-) GEM globalisation --------------------------------------------------------------------------- By Paul Jones As you might know, the Atari market is being swamped by clones. These clones are not totally compatible with games etc because they use illegal direct hardware registering instead of system calls... All modern programs should not assume that the computer that it's being ran on is an Atari - Atari software now runs on the PC with emulators. For example, art programs. Don't check the hardware registers to find out which screen size/number of colours there are, use the VDI to give you your answer. Likewise, if you're creating a GEM program, don't use GEMDOS to return your keypresses, use the AES's evnt_multi or evnt_keybd. Remember if you're trying to get the address of the mouse routines (kbdvbase&+16) or the VBL list, don't assume the address of these lists are always the same - this should be the case for all software. Contact and contribution --------------------------------------------------------------------------- You can email me at paulat.jones@zetnet.co.uk, alternatively you can snail mail me at: Paul Jones 7 Coppice Close Worcestershire Droitwich WR9 9JD United Kingdom I welcome any HiSoft BASIC source code, programs you or someone else have created, or text files to be added to the text guide, but I must have permission from the author for it to be included. Contributers --------------------------------------------------------------------------- In no particular order: Paul Jones Email: paulat.jones@zetnet.co.uk URL: http://www.users.zetnet.co.uk/pjones/home.htm Snailmail: 7 Coppice Close Droitwich Worcestershire WR9 9JD England United Kingdom Michael Wensley Email: send the email to Paul above and he'll pass it on Anthony Jacques (who has no interest in HBASIC) Email: jacquesa@zetnet.co.uk Information on SAM for WavePlay lib, C code for AP_TERM (converted to HBASIC by Paul Jones) Copyright status --------------------------------------------------------------------------- HiSoft BASIC is (c) Copyright 1991 HiSoft. All rights reserved. Where possible, all copyright notices have been recorded and noted. This Disk Compilation is (c) Paul Jones 1997. The HBASIC tutorials are (c) Paul Jones/A|C|G 1997. The HiSoft BASIC useful routines and documentation guide may not be reproduced, transcribed, stored in a retrieval system, translated into any other languages or transmitted in any form without the consent of Paul Jones or the A|C|G. The authors of the software routines cannot be accountable for any damage cause to yourself or the computer in any way. All source code contained here in is classed as freeware, this means the author retains copyright of their routine(s) but can be freely used by anyone in their own programs UNLESS STATED.