@Database GameSupport.guide @Author Alastair M. Robinson @Copyright ©1996 by Alastair M. Robinson @node Main "GameSupport package..." GameSupport package V1.2, ©1996 by Alastair M. Robinson ------- ALPHA VERSION - previously unreleased ------- (Better late than never?) @{"The GameSupport module concept" link Modules} @{"Extension commands" link Commands} @{"Procedures" link Procedures} @{"Bugs fixed" link BugsFixed} @{"To do" link ToDo} Please note that this extension is very much in the alpha stage, and the commands implemented so far are certainly not bug-free. The extension currently occupies slot number 23, but this may well change. ***BUG***BUG***BUG*** Not too serious - the protracker playroutine has trouble with finetuned sampled being `slid'. @EndNode @Node Modules "The GameSupport module concept" Several of GameSupport's major features are (read: will be!) `subcontracted' to a separate module. From a technical point of view this has the advantage that the module doesn't need to be pc-relative, but the biggest advantage for the user is that any bugs in the GameSupport modules can be fixed just by replacing the defective module, and will not require that programs using the faulty version be recompiled! The downside though, is that the modules need to be distributed along with any program which uses them. Double-clicking on a module's icon will bring up a user-interface (probably requiring MUI though) which will allow the user to set any options. The data will probably be stored in tooltypes, so non-MUI users will still be able to reconfigure the modules. @{b}Modules planned so far:@{ub} @{b}Controller@{ub} A stub for the GSController libraries. This will let the user choose any game controller for which a GSController library is available - as a programmer you no longer need to worry about how to read a Sega pad, or even a four-player adaptor. The libraries can be in the same directory as this module, so the user needn't install them to Libs:. @{b}AHISoundSystem@{ub} An interface to the AHI Sound System. The AHI Sound System will need to be installed for this to work, though I might include a fallback mode. If you haven't yet met the AHI Sound System, it is basically a re-targettable audio system, giving software a standard way to access any supported sound hardware. Another feature of the AHI Sound System which will be very useful is its ability to mix multiple sound channel, so simultaneous music and sound effects in an AMOS game are a distinct possibility! @{b}ChunkyToPlanar@{ub} Admittedly, this module will be of very little use unless you are proficient in machine code, but AMOSPro is a very competent language for `housekeeping' code which, in assembler, often takes longer to write than the code it's meant to be supporting! @endnode @Node ToDo "Wish list for the future..." Here is a list of features which I intend to implement in the GameSupport extension. @{b}Misc commands@{ub} Asynchronous data loading. I'll make GameSupport spawn a dos process especially to handle data loading, and add a Gsbload command to supplant the existing Bload command. There might also be a Gsaload command, to enable bob, sprite and icon banks to be async-loadable, but this will be far more difficult to implement. @{b}Music commands@{ub} Sample playing commands; I'll probably try to make the ProTracker player capable of playing modules from fast memory at some stage, and this will cause BIG trouble with the existing sample playing commands, so I'll probably replace them, eventually with 8-channel stereo equivalents! @{b}Graphical commands@{ub} Fast map scrolling routines. Don't hold your breath for this one though. 18-bit RGB screenmode! The AGA chipset is capable of showing a HAM8 screen at a resolution of 1280*256, which means that (a tiny bit of colour fringing not withstanding) a screenmode of 320 * 256 in 18bit `true colour' is possible. There's one slight problem though; each 18 bit screen needs 320K of memory! This is the main reason why I haven't gone any further with making my WolfClone run in this mode; I can't afford to dedicate 640K of chip memory to screen buffers! @EndNode @Node Commands "Commands supported by the extension..." @{b}Input...@{ub} @{"Gsreadport()" link Gsreadport} @{"Gsmousedx()" link Gsmousedx} @{"Gsmousedy()" link Gsmousedy} @{"Gssetmousespeed" link Gssetmousespeed} @{b}Music...@{ub} @{"Gstrack Play" link Gstrackplay} @{"Gstrack Loop" link Gstrackloop} @{"Gstrack Gosub" link GStrackgosub} @{"Gstrack Stop" link Gstrackstop} @{"Gstrack Transpose" link Gstracktranspose} @{"Gstrack Volume" link Gstrackvolume} @{"Gscmd8data" link Gscmd8data} @{b}Miscellaneous...@{ub} @{"Gstimer" link Gstimer} @{"Gsiconify()" link Gsiconify} @{"Gspasscode()" link Gspasscode} @{"Gspassdecode()" link Gspassdecode} @{"Gspyth()" link Gspyth} @EndNode @Node Gspyth "The Gspyth function..." @{b}d=Gspyth(x,y)@{ub} This is a highly optimised (at the expense of accuracy) function to apply Pythagoras' theorem. The function is equivalent to d=Sqr(x*x+y*y), but is nearly 3 times as fast when the program is compiled. @{b}x & y@{ub} are the horizontal and vertical lengths (though the order doesn't matter!). Please keep the values of x & y below about 20000, since results become unpredictable if larger numbers are used. Range checking is not performed on the paramters for speed. @{b}Example:@{ub} x1=1 : y1=10 x2=30 : y2=45 dx=x2-x1 : dy=y2-y1 d=gspyth(dx,dy) print "The distance from (";x1;",";y1;") to (";x2;",";y2;") is approximately" print d;", ±1." @Endnode @Node Gspassdecode "The Gspassdecode function..." @{b}l=Gspassdecode(ID$,PASS$,POINTER)@{ub} This function will attempt to unscramble a passcode created with Gspasscode(). @{b}ID$@{ub} MUST be identical to the string used when encrypting. @{b}PASS$@{ub} is a passcode created by Gspasscode(). @{b}POINTER@{ub} is a pointer to a list of longwords in memory (usually a normal AMOS array). The result of this function will be the number of values which have been placed in the array - a 6 character passcode could contain 1, 2, 3 or 4 values, so this number should be checked. If an error occurred (such as the passcode being invalid), the result will be zero. @{b}Please note:@{ub} It is a good idea to apply Upper$() to the passcode in this call, for two reasons; passcodes containing lower case letters won't work, and the string which is passed to this function will be corrupted by this call (for no reason other than my laziness!) You won't notice either problem if you use Upper$(). @{b}Example:@{ub} Dim A(4) l=Gspasscode("Testing",Upper$(PASSCODE$),Varptr(A(0)) @{b}See Also:@{ub} @{"Gspasscode" link Gspasscode} @EndNode @Node Gspasscode "The Gspasscode function..." @{b}P$=Gspasscode(ID$,Pointer,Length)@{ub} This function will take several values in memory and encrypt them into a reasonably unforgeable format. This function is NOT designed to be a high security password system, but it is ideal for generating level codes for games. @{b}ID$@{ub} is a string which will be digested into a seed for the encryption process. This string should be fairly long, e.g. "My game's encryption key", and the string is case sensitive. Passcodes created under one ID will not unscramble correctly under another. @{b}Pointer@{ub} is a pointer to a list of longwords in memory (usually a normal AMOS array). @{b}Length@{ub} is the number of longwords to be encrypted. The returned passcode can contain the upper case letters (A-Z) and the digits 4 to 9. @{b}Please note:@{ub} The passcodes generated by this function have two check digits, and every four bits of information to be encoded require a further character. This means that the passcodes do have a tendency to be rather long, so try to encode as little information as possible, and in particular, avoid negative numbers; the number 1 will encode to a single character within the final code whereas the number -1 will require eight! Numbers from: 0 - 15 will encode to a single character 16 - 255 will encode to two characters 256 - 4095 will encode to three characters 4096 - 65536 will encode to four characters, and so on. @{b}Example:@{ub} Dim A(3) A(0)=10 A(1)=9 A(2)=8 A(3)=7 A$=Gspasscode("Testing",Varptr(A(0)),4) Print A$ @{b}See Also:@{ub} @{"Gspassdecode" link Gspassdecode} @EndNode @Node Gstrackplay "The Gstrack Play command..." @{b}Gstrack Play Bank@{ub} @{b}Gstrack Play Bank , Pos1@{ub} @{b}Gstrack Play Bank , Pos1 To Pos2@{ub} This command starts a ProTracker module playing in the background. The module is played using a CIA timer interrupt, and the playroutine supports all ProTracker commands, plus detection of and notification on the 8 command, which is useful for synchronising screen effects to the music. @{b}Bank@{ub} is the bank which holds the module. @{b}Pos1@{ub} is the position within the song to start playing. @{b}Pos2@{ub} is the end position. When Pos2 is reached, the module will start again from Pos1 (assuming Gstrack Loop isn't turned off!). Pos1 and Pos2 can be changed while the module is playing with the @{"Gstrack loop" link Gstrackloop} command. @{b}Please note:@{ub} There is no Gstrack Load command, so you must use the standard Track Load command instead. @{b}Example:@{ub} Track Load "modules:GuitarSlinger",6 Gstrack Play 6 Wait Key Gstrack Stop @{b}See also:@{ub} @{"Gstrack Loop" link Gstrackloop},@{"Gstrack Stop" link Gstrackstop},@{"Gstrack Gosub" link gstrackgosub},@{"Gstrack Transpose" link Gstracktranspose},@{"Gscmd8data" link Gscmd8data}. @EndNode @Node Gstrackloop "The Gstrack Loop command..." @{b}Gstrack Loop On@{ub} @{b}Gstrack Loop Off@{ub} @{b}Gstrack Loop Pos1@{ub} @{b}Gstrack Loop Pos1 To Pos2@{ub} @{b}Gstrack Loop Defer Pos1 to Pos2@{ub} The first two forms of this command work exactly as the regular track loop commands. @{b}Pos1@{ub} is the position at which the module will start replaying when either the end or Pos2 is reached. @{b}Pos2@{ub} is the position at which the module will end, and restart from Pos1. If the @{b}Defer@{ub} keyword is used, then the new limits will not be set until the current cycle has finished. See later. @{b}Examples:@{ub} Track Load "Modules:GuitarSlinger",6 Gstrack Play 6 Gstrack loop 24 Rem when the module finishes, it will restart at the quiet bit. suppose you had a high score tune at positions 30 to 40, and the main tune was from positions 0 to 29; You might start the high score tune going with: GSTrack Play bank,30 to 40 and you can immediately tell GameSupport to play the main tune when the high score tune has finished with: GSTrack Loop Defer 0 to 29 @EndNode @Node GstrackGosub "The Gstrack Gosub command..." @{b}Gstrack Gosub Pos1@{ub} @{b}Gstrack Gosub Pos1 To Pos2@{ub} This command allows you to play a `jingle' from a module, and then continue with the main song as though nothing had happened. @{b}Pos1@{ub} is the first position of the jingle, and just this pattern will be played if Pos2 isn't supplied. @{b}Pos2@{ub} is the position at which the module will return to the main tune. @{b}Example:@{ub} Track Load "any.tune",6 Gstrack Play 6 wait key Gstrack gosub 10 Rem When a key is pressed, position 10 will be played, after which the module will return to wherever it was beforehand. @EndNode @Node Gstrackstop "The Gstrack Stop command..." @{b}Gstrack Stop@{ub} Stops the current module playing. @EndNode @Node Gstracktranspose "The Gstrack Transpose command..." @{b}Gstrack Transpose Offset@{ub} This unique command allows you to change the pitch at which a module replays. @{b}Offset@{ub} is the change in pitch, in semitones. Notes which are transposed beyond the legal range will be put up or down an octave to fit. @{b}Please note:@{ub} Many modules sound weird when transposed too much, and drumtracks and phrase samples will no longer fit the rhythm if transposed, so use with caution. @{b}Examples:@{ub} Gstrack Transpose 3 : Rem Transpose up three semitones. Gstrack Transpose -12 : Rem Transpose down an octave. @EndNode @Node Gstrackvolume "The Gstrack Volume command..." @{b}Gstrack Volume Level@{ub} This command allows you to change the volume at which a module replays. @{b}Level@{ub} is the volume level for the module, ranging from 0 to 64. @{b}Examples:@{ub} Gstrack Volume 32 : Rem Half volume. For A=64 To 0 Step -1 Gstrack Volume A Wait 5 Next : Rem Smoothly fade out the module. @EndNode @node Gscmd8data "The Gscmd8data function..." @{b}d=Gscmd8data@{ub} This function allows you to detect the use of the 8 command in modules. This command has no effect in ProTracker, and is very useful for synchronising graphical lightshows with music. The function will return a 16 bit number with bits set according to the commands which have occurred since the last call. The 8 command takes the form 8tb, where t is the tick on which the effect will be triggered, and b is the bit which will be set in the cmd8data word. The word will be cleared only when it is read, so this function should be called fairly frequently. @{b}Example2:@{ub} In the module: C-2 1 800 : Gscmd8data will return 1 as soon as this step is reached. C-2 1 830 : Gscmd8data will return a 1, 3 ticks after this step is reached, which, if the module speed is set to 6, will be half a step. In AMOSPro: Repeat Until Btst(3,Gscmd8data) : rem wait for 8t3 command in module. @EndNode @Node Gstimer "The Gstimer function..." @{b}t=Gstimer@{ub} This is a stub for a function in the lowlevel.library (WB3.1), and so the lowlevel.library is *currently* required for this function's operation. The value returned will be the number of 65536ths of a second which have elapsed since the last call to this function. @{b}Please note:@{ub} The first time this call is used, the result will be garbage. The timing is accurate to about 200µs (about 13/65536 of a second!) @{b}Example:@{ub} t#=gstimer :rem This value will be garbage. for a=1 to 200 wait vbl next t#=gstimer :rem this will return the time elapsed since the last call. print t#/65536;" seconds were needed for 200 vblanks." @EndNode @Node Gsreadport "The Gsreadport function..." @{b}js=Gsreadport(gameport)@{ub} This is a stub for a function in the lowlevel.library (WB3.1), and so the lowlevel.library is *currently* required for this function's operation. @{b}gameport@{ub} will be 0 for the mouse port, or 1 for the joystick port. Whichever port you use, this function will automatically detect the type of controller attached. Lowlevel.library V40 supports mice, joysticks and CD32 controllers. If you need to use mouse control, you might find @{"Gsmousedx" link Gsmousedx} and @{"Gsmousedy" link Gsmousedy} (which don't need lowlevel.library) more appropriate. @{b}Example:@{ub} repeat locate 0,0:print hex$(gsreadport(1),8) until key state(69) : rem wait for Esc key. @EndNode @Node Gsmousedx "The Gsmousedx function..." @{b}dx=Gsmousedx(gameport)@{ub} This routine will return the change in the horizontal mouse counter since it was last called. The result will scaled according to the setting of @{"Gssetmousespeed" link Gssetmousespeed} @{b}gameport@{ub} will be 0 for the mouse port, or 1 for the joystick port. @{b}Please note:@{ub} This routine should be called as often as possible, preferably once every vblank, otherwise very fast mouse movements will be misinterpreted. @{b}Example:@{ub} x=0 repeat add x,gsmousedx(0) locate 0,0:print x;" " until key state(69) : rem wait for Esc key. @{b}See also:@{ub} @{"Gsmousedy" link Gsmousedy},@{"Gssetmousespeed" link Gssetmousespeed}. @EndNode @Node Gsmousedy "The Gsmousedy function..." @{b}dy=Gsmousedy(gameport)@{ub} This routine will return the change in the vertical mouse counter since it was last called. The result will scaled according to the setting of @{"Gssetmousespeed" link Gssetmousespeed} @{b}gameport@{ub} will be 0 for the mouse port, or 1 for the joystick port. @{b}Please note:@{ub} This routine should be called as often as possible, preferably once every vblank, otherwise very fast mouse movements will be misinterpreted. @{b}Example:@{ub} y=0 repeat add y,gsmousedy(0) locate 0,0:print y;" " until key state(69) : rem wait for Esc key. @{b}See also:@{ub} @{"Gsmousedx" link Gsmousedx},@{"Gssetmousespeed" link Gssetmousespeed}. @EndNode @Node Gssetmousespeed "The Gssetmousespeed instruction..." @{b}Gssetmousespeed speed@{ub} This routine will set the scaling applied to the results of @{"Gsmousedx" link Gsmousedx} and @{"Gsmousedy." link Gsmousedy} @{b}Speed:@{ub} the speed argument must be greater than 0. The maximum value is 32760(!). For those interested, the dx and dy values are calculated like this: dx=(dx*(speed+7))/8 @{b}Example:@{ub} Gssetmousespeed 1 : Rem Normal speed Gssetmousespeed 5 : rem 1.5 times normal speed Gssetmousespeed 9 : rem twice normal speed @{b}See also:@{ub} @{"Gsmousedx" link Gsmousedx},@{"Gsmousedy" link Gsmousedy}. @EndNode @Node Gsiconify "The Gsiconify function..." @{b}error=Gsiconify(IconText$)@{ub} @{b}error=Gsiconify(IconText$,IconPath$)@{ub} This routine will create a workbench AppIcon. This function needs at least workbench 2 to work. @{b}IconText$:@{ub} This string will be placed under the icon. @{b}IconPath$:@{ub} the filename of a workbench icon (.info will be added), the image of which will be used for the appicon. @{b}Please note:@{ub} You MUST send the AMOS screen to the back yourself, because while this function is operating, the Amiga-A keypress will be disabled. This function will not handle errors in the normal way, since this could leave the workbench screen at the front, and the user with no idea why. That's why Gsiconify is implemented as a function; the returned value will be 0 if the icon is double-clicked on, and 1 if an error occurred. @{b}Examples:@{ub} Amos lock Amos to back E=Gsiconify("Testing") Amos to front Amos unlock Amos lock Amos to back E=Gsiconify("Testing","data/MyIcon") Amos to front Amos unlock @EndNode @Node BugsFixed @{b}1.9.1996 Gsiconify():@{ub} Problems with using a specified icon image fixed: I forgot that AMOS strings aren't null terminated! The icon is now sought relative to the current directory, so a full path is no longer needed. @{b}28.9.1996@{ub} Extension used to crash when used on Kickstart 1.3. This was due to faulty library handling code trying to close lowlevel.library even if it wasn't open! @EndNode @Node Procedures "Procedures..." @{b}GameSupport Procedures@{ub} ©1996 by Alastair M. Robinson. @{"SerialLink.AMOS" link SerialLink} @EndNode @Node SerialLink "The SerialLink procedures..." These procedures were written in an attempt to make serial linkups as easy as possible. These routines are used within my own Wolfenstein Clone, and seem to work very well. The procedures are: @{b}_SERIALLINK@{ub} This procedure will try to establish a serial link with the remote machine. You should add to this routine where shown to provide a cancel option for the user. @{b}_SERIALCLEANUP@{ub} This routine closes the serial device. @{b}_SYNCHRONISE@{ub} If your game has to do any loading from disk, you should call this routine afterwards. The program will pause until both machines have reached this point. @{b}_SERIALSEND[_DATA,_TYPE,_LENGTH]@{ub} Use this procedure to send a message to the remote machine. You can send up to four bytes at a time, along with a `type' field, which can be used the other end by your program. _Data is simply the number to be sent across the link. _Length can be between 0 and 4, inclusive, and is the number of bytes to be sent. If _Data is less than 256, you can use a length of 1, whereas a length of 2 will suffice for any number less than 65536. If you're not sure what _length should be, just set it to 4 - lower lengths just save a bit of time by not sending 0's. Please note: If you're sending a negative number across the link, you must set _length to 4. @{b}_HANDLESERIAL@{ub} This procedure should be called once every game loop, and will not return until all pending serial messages have been handled. You will need to add your own code to this procedure to handle messages from the other machine. @{b}_SERIALREAD@{ub} You shouldn't need to call this routine directly, it is called by the provided _HANDLESERIAL routine. @EndNode