>>>>>>>>>>>>> IntyBASIC user's manual <<<<<<<<<<<<<<< by Oscar Toledo G. (c) Copyright 2014-2020 Oscar Toledo G. http://nanochess.org/ E-mail: biyubi@gmail.com First developed: Jan/14/2014 Last revision: Jun/17/2020. >>>>>>>>>>>>>> Legal notice This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages or loss arising from the use of this software. It is prohibited to modify, decompile, disassemble or reverse engineer this software. All trademarks are property of their respective owners. >>>>>>>>>>>>>> Changes in this version v1.4.2 Jun/17/2020 o Added escape sequence \\ for inverse bar inside strings. o Limited numeric escape sequences to 3 digits. o Added SCREEN ENABLE/DISABLE for enabling/disabling video. o Generated metavariable jlp wasn't 3 when using FLASH. v1.4.1 Jun/12/2019 o Added BITMAP NORMAL, BITMAP INVERSE and BITMAP MIRROR_X for adjusting interpretation of following BITMAP statements without re-entering everything. o Optimizes POKE to direct address with a single MVO. o Solved bug in local labels preceded with comma, it required a space before. o Solved bug compiling nn = (varptr sfx2_v(0)-varptr sfx2_n(0))-sfxstep o Solved bug in MUSIC.PLAYING (relative to new music format) o Solved bug in music player because new _ntsc interpretation. v1.4.0 Jan/10/2019 o Added contrib/accel.bas it shows how to move sprites by fractions of pixel (contributed by intvnut) o Added samples/rain.bas to show animate rain and moving trees. o Added samples/pumpkin_master.bas as another example of a fully working game. o VOICE INIT now "shuts up" the Intellivision (contributed by intvnut) and the initialization is done in automatic form at start of program. o FLASH INIT SIZE to choose Flash memory size. o Allows constants in DATA PACKED. o Detects wrong flow of control (GOTO to PROCEDURE or GOSUB to non-PROCEDURE) o Tracker allows playing 8 channels of music (using ECS PSG) o Added ON expr FAST to avoid two instructions. o Added MUSIC GOSUB, MUSIC RETURN, MUSIC VOLUME and MUSIC SPEED. o Generates warnings for AND/OR/XOR and small operators non-parenthesized. o Now direct CONT1, CONT2, CONT3 and CONT4 generate 8-bit results. o Solved bug where IF CONT.B0 THEN wouldn't work, also ABS and SGN. o Name mangling for assembler now uses original names, easing assembler interface. o Now detects failure of flow control when using GOTO to jump wrongly between procedures. o Support for local labels (using period character before a label, uses last global label as prefix) o Compatibility with Tutorvision consoles. o Solved bug in PLAY SIMPLE (always was processed as NO DRUMS) o Added new IntyColor flags for processing bitmaps as 8x16 and selecting size of block of GRAM definition. o Added ECS.AVAILABLE flag. o Allows the --cc3 option to change the address of RAM memory. (allows Keyboard Component compatibility) v1.2.9 Nov/07/2017 o Moved screen clearing at the very start of program to avoid brief title screen in Sears Intellivision. o Added missing C7 note in internal tables. o MUSIC.PLAYING failed with MUSIC JUMP. o More optimization saving flags state across instructions. o Solved bug in PEEK optimization when source address was incremented between two PEEKs. o More indications in manual, including documenting CONT3 and CONT4. o VOICE.AVAILABLE for checking Intellivoice available. o VOICE.PLAYING for checking Intellivoice playing. v1.2.8 Oct/07/2016 o Added DATA PACKED for fitting two letters per word. o Added OPTION WARNINGS for enabling/disabling warnings during compilation. o Added OPTION EXPLICIT for generating errors for any variable used not declared previously with DIM. o Now 16-bits memory segment for JLP/CC3 has new as1600 attributes "=RW" (required for LTO-Flash) o Warns about weird constants in FOR TO v1.2.7 Sep/08/2016 o Allows to concatenate lines using the character \ at the end of a line. o Now optimizes access to arrays when using same index even if different array or offset. o Solved bug where DEFINE VARPTR swallowed one extra lexical component. o Solved bug where 1024-x*x generated wrong code. o Solved bug where PRINT "string" as first statement would write in non-screen memory. o Minor edit in manual (definition of BORDER) v1.2.6 Jul/31/2016 o Detects when PROCEDURE isn't finished at end of source code. Also starting a new PROCEDURE without closing the previous one now is an error instead of a warning. o Added DATA VARPTR to allow arrays of pointers to arrays and/or variables. o Generates warning when using DEFINE and requesting more than 16 GRAM to define. o Internal: the mode_select variable now preserves in bit 0 the actual mode. o Solved bugs in multiplication by 126 and 127. o Solved bug in usage of JLP acceleration. (wrongly cached registers) o Corrected contrib/clowns.bas (catsfolly) it broke with a change in constants.bas o Added contrib/Gram2GromFont.bas (GroovyBee) showing how to take the GROM font and creating an entirely new font. o Added contrib/TinyFont.bas (GroovyBee) showing how to display 40 columns using a 4 pixel wide font. o Added manual notes about assembly language conventions for USR and CALL. v1.2.5 Feb/16/2016 o Added UNSIGNED statement, allows to make unsigned comparisons. o Added PLAY VOLUME statement. o Added NO DRUMS syntax to PLAY. o Added MUSIC JUMP statement. o Added MUSIC.PLAYING expression. o Added CALL statement (like USR but outside expressions) o DATA allows for string literal. o DO statement followed by colon now isn't taken as label. o Corrected bug in PAL detection. o Updated constants.bas (corrections and new constants for Coloured Squares mode) and keypad.bas sample. o Added contrib/ColouredSquares.bas a sample of drawing lines in Coloured Squares mode by GroovyBee. o Added samples/bats.bas (animated bats) o Added samples/envelope.bas (using envelope sounds) v1.2.4 Sep/25/2015 o Optimizes sequences of ANDI/XORI instructions. o Gives warning in case of variable assignment to name previously used with CONST. o Solved bug where ELSEIF should be finished with ELSE. o A few warnings emitted wrongly an error code. o Warns about assignment to internal variable names. v1.2.3 Sep/01/2015 o Added SIGNED statement to indicate arrays or variables of 8-bits signed. o SPRITE statement now allows expression on MOB index. o SCREEN allows for sixth argument to support a wide origin screen, useful for horizontal scrolling or to display a fraction of a big map. o Solved bug where warnings were treated as errors for final return code of command line. o Solved bug where some warnings couldn't be disabled. o New sample: landscape.bas (additional SCREEN syntax) v1.2.2 Aug/24/2015 o New FLASH statement allowing access of Flash memory available in JLP cartridges. o New FLASH.FIRST and FLASH.LAST read-only variables. o Added new sample: flash.bas o Added new contribution: 42k.bas (GroovyBee) it shows how to create a maximum size IntyBASIC program. o When using --jlp option the stack is now keep in internal system RAM. o Generates warning if value bigger than 8 bits assigned to 8 bits variable. Note this is a warning instead of an error because sometimes are used negative values in 8-bits variables that can be used for arithmetic purposes with another 8-bits variables and doesn't cause any harm. o Generates error if TO value is bigger than 8 bits when using with 8 bits variable. o Generates warning for defined but unused labels. o Generates error for undefined labels. o Generates error for redefined labels. v1.2.1 Aug/16/2015 o Added #BACKTAB array (direct access to screen) o Optimized code generation for POKE. o Optimized plus constant followed by minus constant. o Solved bug where block IF code generation was wrong. o Solved bug where it got stuck in DEF FN with syntax errors. v1.2 Aug/08/2015 o New option -w for disabling compilation warnings. o Strings now allowed in DEF FN and as arguments to macro. o Added support for block IF/ELSEIF/ELSE/END IF. o Added statement DO/LOOP o Added statement EXIT, use as EXIT FOR, EXIT WHILE or EXIT DO. o New LEN() function. o New POS() function. o Added automatic seed of pseudorandom generator with RAM trash. o Initializes ECS PSG sound. o Error or warning inside INCLUDE indicates file. o Solved bug where nested macros wouldn't work. o Solved several bugs in macros for constant multiplication. o Added new contribution (tcg.bas) by catsfolly. o Many enhancements for the IntyColor utility. o Option -m for creating MOB (for third/fourth color in same block) o Option -c to not include constants.c (option -m) o Option -r to create BMP report colored (error/GRAM/GROM) o Option -g to indicate how to use the MOB (use with -m) v1.1 Jul/14/2015 o New RANDOM() function o New DEF FN statement for macro expressions. o Experimental CONT3 and CONT4 support, no keypad decoding (ECS) o INCLUDE now allows quotes and searchs also in library path. o Generates warning for assigned/non-read variables and also for read/non-assigned variables. o Multiplication algorithm optimized (no more successive addition that could take a long time, 2 seconds in worst case) o New #MOBSHADOW array. o New fast division/remainder algorithm for special case of only variables as arguments. o Solved bug where multiplication by 0 would take a long time. o Now optimizes multiplication by $0200, $0400 and $0800. o Solved bug where ECS code was always included. o Solved bug where some divisions were signed. o More optimization at code generation when the right operand is the most complex. o Some peephole optimization for code generation (at last saves code internally for further processing) * Avoids reloading register with constant if still available * Avoids reading memory in register if just written * Combines pairs of instructions in more optimum ways. * Array reading array(const) is more optimum * Common subexpression removal for simple index into array. * Optimization for multiple substraction. * Optimization for comparisons. * Optimization for IF expr THEN GOTO. * New contributions: keypad (GroovyBee), intro (Tarzilla) and Hello (DZ-Jay) v1.0.4 Apr/23/2015 o Added support for ECS secondary PSG (only in SOUND) o Added RAND(range) for getting random number in range 0..range-1 o Slight optimization in PRINT with spaces. o Modulus optimizes every power of 2. o Multiplication by 32, 64 and 128 optimized. o Division by 32, 64 and 128 optimized. o Added intvnut routine for fast multiplication (included only if you use variable * variable) o Solved bug where RETURN inside IF was taken as RETURN at end of PROCEDURE. o Solved bug in 8-bit and 16-bits variables space counting. Now it is exact. v1.0.3 Feb/17/2015 o Added new parameter PLAY NONE o Added new statements WHILE/WEND o Added SGN function. o It doesn't take some statements as a label if followed by colon. o Returns error code to command shell in case of compilation error or warning. v1.0.2 Jan/25/2015 o Support for changing title of compiled program. (it's shown by emulators and multicarts) o Support for Cuttle Cart 3 extra RAM. (same as JLP but without hardware acceleration for multiplication and division) o Support for CONT.* syntax, checks both controllers. o Support for ON FRAME GOSUB. v1.0.1 Dec/12/2014 o Statements DEFINE, SCREEN and PLAY allow to use an array as reference, in order to ease dynamic modification of data. o DEFINE statement allows VARPTR syntax. o Corrected total of free variables, it indicated one more than available. o Again optimized code generation for PRINT. o Optimized code generation for array access and PEEK. o Optimized code generation for trees of addition and substraction with constant. o Uses ultra-optimized macro for multiplication up to 127. (provided by DZ-Jay) o Speed up of code for keypad decoding. o Windows version of IntySmap, I forgot to include it before! o Many thanks to Kiwi for contributing Apple Catcher as a game sample. o Many thanks to catsfolly for contributing Clowns&Ballons as a game sample. v1.0 Nov/21/2014 o PRINT allows to display decimal numbers using a library provided by intvnut. o Support for Intellivoice via VOICE statement. o Added --jlp switch for support of multiplication/division acceleration via hardware. o --jlp switch also activates use of 16-bits RAM memory at $8040-$9f7f (almost 8000 words for arrays/variables) o Added ABS function. o Added support for READ A(x) o Added USR function to call easily assembly functions. o Added VARPTR function to pass addresses to assembly functions. o Added DEFINE ALTERNATE o Optimization of code generation for expressions involving substraction and cases a+(-b) and a-(-b). o Optimization of code generation for IF A AND 2 o Optimization of code generation for PRINT with strings. o Optimization of code generation for = and <> with zero. o Removes extra RETURN at end if the statement combination RETURN/END is used. o MUSIC statement alone doesn't activate tracker module. Only if PLAY is used (useful to deactivate music) o Warns of PROCEDURE start without ending previous PROCEDURE o Warns of END used without starting PROCEDURE o Added IntySmap utility for mapping assembly code to IntyBASIC o Added extra information to IntyBASIC assembler output for source-level debugging. o Added intbas.pl script for structuring directories. v0.9 Oct/10/2014 o Added ON GOTO/GOSUB statement. o Added STACK_CHECK statement. o Added INCLUDE statement. o In statement DEFINE now are allowed expressions in parameters for card number and total cards. o Added fixed numbers 8.8 style and fixed add and substract operators (+. and -.) o Multiplication and division optimized for constant 256. o Remainder optimized for constants 32, 64, 128 and 256. o Added extra description for SOUND, MUSIC, MODE and DEFINE statements. v0.8 Aug/26/2014 o Generates warning if unable to open prologue/epilogue files. o Shows total variable space used if exceeds available space. o Support for binary numbers, using syntax &01010101 o Integrates music player and PLAY/MUSIC statements. o Integrates PAL/NTSC detection. v0.7 Apr/02/2014 o Added support to access card codes of Intellivision letters in expressions. o New MODE and SCREEN statements, so now all Intellivision video operations are controlled with IntyBASIC statements, no further need for POKE/PEEK. o Comparisons now return $ffff for true results, useful with NOT o Solved bug where CONT2 wasn't working. o Following two are experimental: o Now CONT?.B0 B1 and B2 are checking individual buttons. o Added support for controller keypads. v0.6 Mar/02/2014 Solved bug where FOR STEP would go beyond admisible values. Support for constants via CONST statement. Added example of sprite offset correction in SCROLL.BAS v0.5 Feb/26/2014 Accelerated assembly language routines for collision registers. Added SCROLL and BORDER statements. Support for library path in arguments. v0.4 Feb/11/2014 Solved bug in assignation to array with constant index. v0.3 Feb/06/2014 Added DIM statement and indexed array accesses. Solved bug of undetected extra characters in line. Added memory limit detection for variables. v0.2 Feb/03/2014 More definition variations available with BITMAP statement Added another sample title.bas Supports officially Mac OS X 10.6 (before only 10.8 and 64-bit) Supports officially Linux. v0.1 Jan/28/2014 First release >>>>>>>>>>>>>> Description IntyBASIC is an integer BASIC compiler for Intellivision. It works as a cross compiler over a PC, Mac or Linux and generates assembler code that can be processed by as1600 (included with the jzintv emulator) Platforms requirements: o PC with Windows XP or better. o Mac OS X 10.6 or better. (universal 32/64-bits binary) o Linux. The current limitations are: o Division and remainder (modulo) operators treat numbers as unsigned. o The constants 32768-65535 don't imply unsigned numbers, if these are used in a comparison with a variable, the variable should be marked as UNSIGNED. o ASM cannot be used inside DEF FN. o Using PRINT for numbers always show numbers as unsigned from 0 to 65535. Usage: intybasic in.bas output.asm [library_path] intybasic --jlp in.bas output.asm [library_path] intybasic --cc3 in.bas output.asm [library_path] intybasic --title "My cute game" in.bas output.asm [library_path] The following modules are automatically included as prologue and epilogue of your generated code and they set important variables and helper code: intybasic_prologue.asm intybasic_epilogue.asm By default these are taken from the current directory unless you choose a library path. Afterwards you should assemble your program using as1600: as1600 -o output.bin -l output.lst output.asm And finally you can test it using jzintv or Nostalgia emulators: jzintv output.bin Normal run jzintv --jlp output.bin Run with JLP support jzintv -v1 output.bin Run with Intellivoice support Alternatively you can load the program into a CuttleCart, Intellicart or LTO-Flash for testing on a real Intellivision. See below for information about source-level debugging. The following sample programs are included: samples/bats.bas Animated bats using new statements for loops samples/constants.bas Constants library (used by all samples) samples/controller.bas Test program for controllers samples/envelope.bas How to use envelope volume generator of the sound chip samples/flash.bas Sample of how to use Flash memory in JLP cartridges. samples/frame.bas Sample of ON FRAME GOSUB samples/game1.bas A simple letter shooting game. samples/game2.bas A simple labyrinth game with enemies. samples/lander.bas Lunar Lander-style game samples/music.bas Simple example of music playing samples/pak.bas Labyrinth game eating points with ghosts samples/pumpkin_master.bas Pumpkin Master game. samples/rain.bas Rain animation. samples/screen.bas MODE statement test samples/scroll.bas Example of how to use scrolling. samples/sprites.bas Moving sprites sample. samples/test.bas Compiler tester. samples/title.bas Animated tile for title screen samples/voice.bas Simple example of Intellivoice contrib/42k.bas Example of how to use the 42K words maximum memory map contrib/accel.bas Moving sprites with subpixel fractions by intvnut. contrib/AppleCatcher.bas Apple Catcher game by Kiwi. contrib/clowns.bas Clowns & Ballons game by catsfolly. contrib/ColouredSquares.bas Uses Coloured Squares mode to draw Bresenham lines contrib/constants.bas Constants library (same as samples) contrib/Gram2GromFont.bas Converts GROM font to different fonts by GroovyBee. contrib/hello.bas Hello World by DZ-Jay contrib/intro.bas Intro to IntyBASIC by Tarzilla. contrib/keypad.bas Keypad test by GroovyBee. contrib/tcg.bas Trollish Comment Generator by catsfolly. contrib/TinyFont.bas Small font generator at 40 columns by GroovyBee. The following utilities are included: IntyColor Converts a bitmap image to IntyBASIC source code/graphics IntySmap Converts a smap file to reference IntyBASIC source code. Useful with jzintv debugger (option -d and --src-map) See section below for full information. >>>>>>>>>>>>>> Supporting the developer If you find IntyBASIC useful, please show your appreciation making a donation via Paypal ($9 USD suggested) to b-i+y-u+b-i (at) gmail.com If you find a bug, please report to same email and I'll try to look into it. Because lack of time I cannot guarantee it will be corrected. Also you can get the book "Programming Games for Intellivision" that is a book version of this manual, and also including an introductory course to game programming (Game of Ball, Monkey Moon, Space Raider & Bouncy Cube). Paperback: https://www.lulu.com/en/en/shop/oscar-toledo-gutierrez/programming-games-for-intellivision/paperback/product-1p7mvg87.html Hardcover: https://www.lulu.com/en/en/shop/oscar-toledo-gutierrez/programming-games-for-intellivision/hardcover/product-16ye5m5n.html Ebook: https://nanochess.org/store.html >>>>>>>>>>>>>> IntyBASIC language specification Execution starts at init point of BASIC program. Syntax per line: [label:] statement[:statement] [' comment][\] MAIN: PRINT "HELLO" ' Prints hello Multiple statements are allowed, but these must be separated by colons. Variables are created simply by being used. Labels are created simply by being used. You can use a period before a label name to mark a local label. The local label real name is based in the most recent global label (any label that doesn't start with a period) concatenated with the local label. A variable name starts with a letter or # and is followed by letters, numbers, or the underscore character. Variables and arrays (see DIM and bottom section for "exact" variables allowed) can be 8 bit (maximum 179 available) or 16 bit in size (maximum 28 available). Variables are 8 bit by default. To define a 16 bit variable use # as the starting character of the variable's name. x y #score Note that if you use the # prefix you should use it everywhere in your program. Variables with the same name but without the # prefix are treated as different 8 bit variables. All variables are initialized with the value 0 (zero) when they are created. Also, IntyBASIC will warn you if you exceed the number of available variables. Concatenation of lines is available via the \ character. It concatenates the current line with the following line as a single long line. The following example is completely valid: PR\ INT\ "HELL\ O" And will be processed as PRINT "HELLO" The following statements are available: REM comment ' comment Everything between REM and the end of the line is treated by the compiler as a comment. SIGNED name[,name] Indicates that names are signed variables/arrays. This only applies to the 8-bit variables that are unsigned by default. Notice that this adds two machine instructions to extend the sign of each 8-bit signed variable read, although IntyBASIC will try to optimize them. Usually you can develop your programs without using this keyword, but it's available if you really need it. UNSIGNED name[,name] Indicates that the names are unsigned variables/arrays. This only applies to the 16-bit variables when doing comparisons of less or greater than, including FOR statements. Notice that this can add one extra machine instruction to each comparison, this depends on the comparison direction. This is very useful for score routines up to 65535 or to create subroutines with 32-bit values. CONST [name]=[constant expression] Assigns a name to a constant expression. The compiler will replace all instances of this name, in all expressions, with the number. These names have priority over variable names. This is like a compiler directive, it doesn't generate code and it can appear anywhere in the program but it will be treated as a constant from the point of appearance onwards. GOTO label Go to label. It's erroneous to jump from inside a PROCEDURE to outside of the same PROCEDURE. IntyBASIC will generate an error message in this case. ' GOSUB label Go to subroutine at label (must be a PROCEDURE). label: PROCEDURE [code for subroutine] END Create a PROCEDURE callable by GOSUB. It's important that PROCEDURE is on the same line as the label. END implies an automatic RETURN. RETURN Return from subroutine (PROCEDURE). Also can be used to return early from a PROCEDURE. FOR A=start TO end [STEP increment] NEXT ' Also supported NEXT A FOR A=1 TO 5 ' Loop [Variable A will contain 1,2,3,4,5] NEXT A FOR A=1 TO 5 STEP 2 [Variable A will contain 1, 3, 5] NEXT A FOR A=5 TO 1 STEP -2 [Variable A will contain 5, 3, 1] NEXT A Looping statement. The start, end and step expressions can be complex expressions, instead of only constants or variables. Notice that you can only use regular variables for the loop variable, not array variables. There is a small quirk if you're using an 8-bit variable and the TO expression is pretty complex and reaches 0 or 255, the loop can be infinite. WHILE expr:[statement]:WEND WHILE expr [statement] WEND Looping statement that keeps looping as long as the expression evaluates to non-zero. DO WHILE expr:[statement]:LOOP DO WHILE expr [statement] LOOP DO UNTIL expr:[statement]:LOOP DO UNTIL expr [statement] LOOP DO:[statement]:LOOP WHILE expr DO [statement] LOOP WHILE expr DO:[statement]:LOOP UNTIL expr DO [statement] LOOP UNTIL expr Looping statements that keep looping WHILE expression evaluates to non-zero, or UNTIL expression evaluates to non-zero. EXIT FOR Exits current FOR loop, jumps directly to the line that follows NEXT. EXIT WHILE Exits current WHILE loop, jumps directly to the line that follows WEND. EXIT DO Exits current DO loop, jumps directly to the line that follows LOOP. IF expr GOTO [label] IF expr THEN [statement] IF expr THEN [statement] ELSE [statement] IF expr THEN [statement] END IF IF expr THEN [statement] ELSE [statement] END IF IF expr THEN [statement] ELSEIF expr THEN [statement] END IF IF expr THEN [statement] ELSEIF expr THEN [statement] ELSE [statement] END IF Decision statement ON expr GOTO [label],[label],[label] ON expr GOTO [label],,[label] ON expr GOTO ,,[label] ON expr GOSUB [label],[label],[label] ON expr GOSUB [label],,[label] ON expr GOSUB ,,[label] ON expr FAST GOTO ON expr FAST GOSUB Decision statement The expression is evaluated and if the result is zero, the first label is taken, if the result is one, the second label is taken, and successively up to any number of labels. If GOSUB is used then you must make sure that each label is linked to a PROCEDURE. If an option has no label or if the expression exceeds the number of labels, the execution flow continues with the following statement after ON. This statement can be made faster in execution using the FAST modifier, it will avoid checking boundaries, if your list of labels doesn't cover the full expression range then your PROGRAM WILL CRASH. ON FRAME GOSUB label On each video frame interrupt, the IntyBASIC core will call the indicated PROCEDURE. This doesn't generate any code and should only appear once in your program. Also, it’s important to keep in mind this procedure could be called even before your initialization routines are executed. The only valid assumption is that every single variable is zero after booting. Also it's your responsability that the code doesn't take too long to execute, otherwise video frame interrupts will accumulate and your memory stack will overflow. POKE address,data Poke memory with data. WAIT Waits for the next frame interruption (1/60 of a second for NTSC or 1/50 of a second for PAL) OPTION WARNINGS ON OPTION WARNINGS OFF Enable/disable the compilation warnings. Note that if you disable warnings at the end of your program, you won't have the list of non-used variables. OPTION EXPLICIT OPTION EXPLICIT ON OPTION EXPLICIT OFF Makes it mandatory to declare each variable with DIM before said variable can be used. DIM variable DIM variable[,variable] Declares a variable. Useful in combination with OPTION EXPLICIT. UNSIGNED and SIGNED are still applied separately. DIM var(size) Creates an array of data called 'var' of size 'size' elements. Counting starts on zero, so DIM A(10) creates an array of 0 to 9. Also you can create arrays of 16-bits numbers, using DIM #BIG(10) The array can be accessed as follows: A(1)=A(1)+5 A(X)=A(Y)-2 The DIM statement is like a directive, meaning it doesn't generate code and it can appear anywhere in the program. The definition will start from the line of the DIM statement. RESTORE label READ var READ var,var2 label: DATA constant_expr[,constant_expr] DATA string DATA PACKED string DATA PACKED constant_expr[,constant_expr] DATA VARPTR a DATA VARPTR b(constant_expr) The RESTORE statement will reset an internal pointer to the indicated label that should be annex to a DATA statement, this is useful for defining tables and/or graphics. Numbers can be in the 16-bit range. READ will automatically limit to variable size, for example if 16-bit data is read into a 8-bit variable, it will translate only the lower 8-bit. READ A ' Reads data into A, limiting to 8 bits READ #A ' Reads data into #A, no limitations. ' Notice A and #A are different variables. READ A(B) ' Reads data into A(B) READ #A(B) ' Reads data into #A(B) After reading a value, the internal pointer will point to the following value. All data contained in DATA can also be accessed using the familiar array-indexing syntax, like this: FOR A=0 TO 4 PRINT AT TABLE(A),"Z" NEXT A TABLE: DATA 21,42,63,84,105 String data will be converted to Intellivision character codes (just like in PRINT but not multiplied by 8 for screen) The string data with DATA PACKED will store two Intellivision character codes per word (higher byte of word contains first letter, lower byte of word contains following letter). The constant data with DATA PACKED will be handled the same way. If DATA PACKED is given an odd number of bytes to process, it will add a zero byte to complete the last word. DEFINE card_num,total,label DEFINE card_num,total,VARPTR label(expr) DEFINE ALTERNATE card_num,total,label DEFINE ALTERNATE card_num,total,VARPTR label(expr) Loads graphics into GRAM "card_num" (0-63) for a total of "total" cards. label points to the graphics (DATA or BITMAP). Label can also reference a 16-bit array for dynamically defined GRAM (different from the static ones preserved in Read-Only Memory or ROM) DIM #graphic(4) DEFINE 0,1,#graphic And the VARPTR syntax allows us to select a bitmap from multiple definitions. The graphics will be loaded in the next video frame (you can use a WAIT to synchronize with the loading). Notice that there is an approximate limit of 18 GRAM cards that can be loaded per frame (this was measured with an emulator in NTSC mode). This limit is reduced to 16 GRAM cards per frame when using the music player (when using the PLAY statement). This limit is further reduced to 13 GRAM cards per frame when using the full ECS music player. Notice that there are two variants, namely DEFINE and DEFINE ALTERNATE. This allows you to change two cards sets in one frame. This can be useful because if you use DEFINE multiple times per frame only the latest one is taken in account. SOUND 0,[VALUE 12 bits],[VOL 0-15] Channel A SOUND 1,[VALUE 12 bits],[VOL 0-15] Channel B SOUND 2,[VALUE 12 bits],[VOL 0-15] Channel C SOUND 3,[VALUE 16 bits],[TYPE 0-15] Volume envelope (frequency/shape) SOUND 4,[NOISE 5 bits],[MIX] Noise and mix register ($38 value by default) Only for the secondary PSG in ECS add-on module SOUND 5,[VALUE 12 bits],[VOL 0-15] Channel A SOUND 6,[VALUE 12 bits],[VOL 0-15] Channel B SOUND 7,[VALUE 12 bits],[VOL 0-15] Channel C SOUND 8,[VALUE 16 bits],[TYPE 0-15] Volume envelope (frequency/shape) SOUND 9,[NOISE 5 bits],[MIX] Noise and mix register ($38 value by default) Desired frequency value can be calculated as: value = (3579545 / 32 / frec) Please take note this change for PAL consoles: value = (4000000 / 32 / frec) Only a constant (0-9) can be used as the first parameter of SOUND. For channels A, B and C, if you use volume 48 the PSG will use the volume envelope (see SOUND 3) Use volume 0 to deactivate sound channels instead of mixer bits. Also don't use a zero value for frequency parameter in channel A, B or C, it's better to use 1 in order to get a fast response when changing frequency. More info about the PSG at: http://spatula-city.org/~im14u2c/intv/jzintv-1.0-beta3/doc/programming/psg.txt http://spatula-city.org/~im14u2c/intv/gi_micro_programmable_tv_games/page_7_100.png http://spatula-city.org/~im14u2c/intv/gi_micro_programmable_tv_games/page_7_101.png http://spatula-city.org/~im14u2c/intv/gi_micro_programmable_tv_games/page_7_102.png http://spatula-city.org/~im14u2c/intv/gi_micro_programmable_tv_games/page_7_103.png http://spatula-city.org/~im14u2c/intv/gi_micro_programmable_tv_games/page_7_104.png http://spatula-city.org/~im14u2c/intv/gi_micro_programmable_tv_games/page_7_105.png If you use the music player, the SOUND capabilities are affected. Refer to the PLAY statement later for further information. SPRITE index,x,y,f The first parameter indicates the number of the MOB (0 to 7). Notice that if you use a constant the generated code will be faster. Sprites (MOBs) will be updated during the next frame. X contains coordinate X (0-168) bit 8 = Interaction (suggested always 1) bit 9 = Visibility (suggested always 1) bit 10 = Double size X Y contains coordinate Y (0-95) bit 7 = Draw 16-line sprite. (it should be aligned in even GRAM boundary 0/2/4/8 etc) bits 9-8 = Scale 00= 0.5x, 01= 1x, 10= 2x, 11= 4x bit 10 = X flip bit 11 = Y flip F contains color and card number. bits 2-0 = Lower bits of color bits 11-3 = Card number (0-255 for GROM, 256-319 for GRAM) bit 12 = Upper bit of color bit 13 = Change color stack. The X,Y,F values are written as-is to STIC, please check the specifications at: http://spatula-city.org/~im14u2c/intv/jzintv-1.0-beta3/doc/programming/stic.txt CLS Clears the screen. All cards are set to 0. Also resets the internal cursor position to the top-left corner of the screen. PRINT [AT [expr]][COLOR [expr]][,]"string"[,"string"] Prints the given string at the current cursor coordinate (or selected via the AT value 0 to 239). The string is automatically converted from ASCII to Intellivision characters and XORed with the current color ($0000-$0007, $1000-$1007 or $2000 for color stack) For Foreground/Background mode, use $0000-$0007, and $0200 is bit 0 of the background color, $0400 is bit 1 of the background color, $1000 is bit 2 of the background color and $2000 is bit 3 of the background color. See the MODE statement below for more information. Notice that the cursor position is not limited so you can write outside of the screen and this will make your program crash! If you want to use a character in GROM beyond character 95 or GRAM characters 256 to 319 you can use the inverted slash as an escape character (by example “\96\256\319”). If you want to use double quotes inside a string you can escape it this way: \" Examples of positioning: PRINT AT 0,"A" ' for upper-left corner PRINT AT 19,"B" ' for upper-right corner PRINT AT 220,"C" ' for bottom-left corner PRINT AT 239,"D" ' for bottom-right corner Example: PRINT AT 84 COLOR (RAND AND 7),"HELLO WORLD" PRINT "HELLO WORLD" ' Starts in previous cursor position PRINT <>expr ' Simple number PRINT expr ' Right-aligned with zeroes to 'const' size. PRINT <.const>expr ' Right-aligned with spaces to 'const' size. Prints decimal number in current position using the current color. You can add the AT and COLOR options. Example: PRINT AT 5 COLOR 6,"Score:",<6>#score,"00" PRINT [AT [expr],]expr[,expr] Pokes a 12-bits value directly into the screen, which is useful for variable things and GRAM cards. For format information please check the STIC specification cited upwards or the F parameter of the SPRITE statement. This also increases the cursor position. Example: Printing a digit in yellow: PRINT (DIGIT+16)*8+6 SCROLL [offset_x],[offset_y],[move_screen] Allows you to scroll the screen pixel by pixel. Offset X and Y can be any number between 0 and 7. Once you pass the frontier of 8 pixels, you can specify how to move all cards on the screen with the move_screen parameter: 1 = Scroll leftwards 2 = Scroll rightwards 3 = Scroll upwards 4 = Scroll downwards The command will be processed during the next frame or interrupt. Notice that if you use the SCROLL statement anywhere in your program, the number of available 16-bit variables will be decreased automatically, because IntyBASIC uses some 16-bit variables for buffering purposes, and it will generate extra code for scrolling. Also notice that the Intellivision video chip (STIC) requires you to correct the position of every sprite when using scrolling. See the sample program SCROLL.BAS for an example. BORDER [color],[mask] Allows you to choose the border color and also to mask the edges for scrolling. Color can be any number between 0 and 15. Mask can be 0, 1 (mask left column), 2 (mask top row) or 3 (mask both) Border and mask will be updated in the next frame. MODE 0,color1,color2,color3,color4 MODE 1 Sets the video mode (Color Stack mode or Foreground/Background mode). This happens in the next video frame (you can synchronize with the WAIT statement) Notice that you cannot use PRINT COLOR until the next WAIT statement has been executed, because the color variable is used to save data. After this COLOR will be reset to 7. In Color Stack mode you can choose the four background colors available in the range 0 to 15. In Foreground/Background mode you have access to 16 background colors but you can only use cards 0 to 63 (basic character set and uppercase letters) and the defined cards 256 to 319. By default IntyBASIC starts in Color Stack mode. SCREEN DISABLE Disables the video output. The current color of border will fill the screen (can be setup using the BORDER sentence). The video can be enabled again with SCREEN ENABLE or using a MODE sentence. SCREEN ENABLE Enables the video output (preserves the previous video mode set by MODE). SCREEN label[,origin_offset,target_offset,cols,rows] SCREEN label[,origin_offset,target_offset,cols,rows,origin_width] This statement is the fastest way to copy screen data to video. Using only "SCREEN label” copies a full screen of 20x12 cards to video. 'label' points to a label inside your program containing the data for the screen, similar to this: my_screen: DATA $0007,$000F,$0007,$000F ' And so... origin_offset is the offset (0-199 or bigger) inside the origin screen target_offset is the offset (0-199) inside the target video screen. cols is the horizontal size (number of columns) of your copy. rows is the vertical size (number of rows) of your copy. origin_width is the origin screen width, useful to copy a sub-portion of a big graphic screen, like a map or when scrolling horizontally. If this parameter is not used, the default value is 20, which corresponds to the Intellivision screen width. This can serve to move large elements in video, or to display beautiful graphics screens. Label can be also a 16-bits array for dynamically-drawn elements. DIM #cards(4) SCREEN #cards,0,0,4,1 BITMAP "00000000" BITMAP "00001111" BITMAP "________" BITMAP "____XXXX" Allows you to draw using binary, you should put BITMAP statements in pairs as they are declared in assembler using DECLE This is most useful when attaching a label and using with DEFINE. Characters taken as zero include: "0" "_" " " "." Every other character will be interpreted as one. BITMAP "________________________" BITMAP "________________________" BITMAP "___XX_____XXX____XXXX___" BITMAP "__X__X____X__X___X______" BITMAP "__XXXX____XXX____X______" BITMAP "__X__X____X__X___X______" BITMAP "__X__X____XXX____XXXX___" BITMAP "________________________" Allows drawing contiguous bitmaps in a more visually pleasing manner. Such wide BITMAP statements must come in groups of eight, and the string width must be a multiple of eight. This is just a shorthand for the following more linear representation: BITMAP "________" BITMAP "________" BITMAP "___XX___" BITMAP "__X__X__" BITMAP "__XXXX__" BITMAP "__X__X__" BITMAP "__X__X__" BITMAP "________" BITMAP "________" BITMAP "________" BITMAP "__XXX___" BITMAP "__X__X__" BITMAP "__XXX___" BITMAP "__X__X__" BITMAP "__XXX___" BITMAP "________" BITMAP "________" BITMAP "________" BITMAP "_XXXX___" BITMAP "_X______" BITMAP "_X______" BITMAP "_X______" BITMAP "_XXXX___" BITMAP "________" BITMAP NORMAL Every BITMAP statement following will be normal. BITMAP MIRROR_X Every BITMAP statement following will be reordered from right to left. BITMAP INVERSE Every BITMAP statement following will reverse bits 0 to 1 and 1 to 0. Useful in Color Stack mode. PLAY SIMPLE PLAY SIMPLE NO DRUMS PLAY FULL PLAY FULL NO DRUMS Activates music player and selects the type of music played, SIMPLE only uses two channels, allowing the programmer to use SOUND 2 for sound effects. FULL will use all three channels, so SOUND cannot be used in this context. The music player plays drums using the noise channel and the mix register. You can deactivate this feature using the NO DRUMS syntax, for example if you want to generate explosion sounds with the noise channel, allowing you to use SOUND 4. Notice that the music player will update the sound channels on every video frame. Also notice that if you use the NO DRUMS syntax, you must insert the following statement just after the PLAY statement in order to set the mix register correctly (the player will not modify it): SOUND 4,,$38 PLAY NONE Deactivate music player. Following this the programmer should turn off all the sound channels, using this code: SOUND 0,1,0 SOUND 1,1,0 SOUND 2,1,0 SOUND 4,1,$38 PLAY VOLUME expr Set volume for music playing: 0 is silence, 1 is minimum volume, 15 is maximum volume. If you use this statement, don't forget to put PLAY VOLUME 15 at start of your program, because volume will be 0 at start (silence). Note this will cause the inclusion of extra code inside your program (around 300 words) and will use a few more cycles during each video frame. PLAY label Plays the music pointed by 'label'. label can also be a 16-bits array for loading dinamically-generated music. IntyBASIC will include automatically extra code for the music player. Music must be in this format: (each MUSIC statement can contain up to 8 arguments) label: DATA 8 ' Ticks per note (there are 50 ticks per second) MUSIC F4,A4#,C5 MUSIC S,S,S MUSIC -,-,- MUSIC REPEAT MUSIC STOP MUSIC JUMP label ' Jump to label (useful for separating intro in looping music) MUSIC GOSUB label ' Go to subroutine at label (only one level) MUSIC RETURN ' Return from subroutine MUSIC SPEED const ' Set ticks per note starting here MUSIC VOLUME const ' Set volume for music starting here (same as PLAY VOLUME) MUSIC C4,F4,- ' Note how C4 extends along 4 tempos and F4 only 2 MUSIC S,S,- MUSIC S,-,- MUSIC S,-,- Identifiers for notes: Note C, D, E, F, G, A, B followed by octave (2-6), C7 is also available. Optionally add # symbol for sharp. Optionally add W, X, Y or Z to specify the instrument. (W for piano, X for clarinet, Y for flute and Z for bass) Setting the instrument carries over in each channel for MUSIC statements played afterwards if the instrument is not specified thereafter. Notice that the instruments waveforms can be altered by modifying the intybasic_epilogue.asm file for your program. Also the programmer can put S to sustain previous note, or can put - for silence. The fourth/eight argument for MUSIC allows simple drums: Valid values are: - none M1 strong M2 tap M3 roll IntyBASIC will detect automatically PAL/NTSC Intellivision and will adjust music timing and frequencies accordingly. Note that if you use more than 4 channels, then the tracker automatically will turn on ECS support to allow you to play 8 channels. (4 in base PSG and 4 in ECS PSG) Note also if you use ECS support then all your MUSIC statements should integrate more than 4 arguments, use at least one silence in 5th argument as play format will be 64 bits instead of 32 bits. PLAY OFF Stops music, if music is currently playing. VOICE INIT Stops playing any voice in Intellivoice and empties queue. The usage of any VOICE statement will cause IntyBASIC to include automatically extra code for Intellivoice initialization at start of program. For no reason your program should restart execution (via assembler code) from the very start of code (address $5000 or $4800) because Intellivoice could hang the system. VOICE PLAY label Lets the Intellivoice perform the voice speech indicated by label. If there is another phrase being spoken or queued then it will be placed at the end of the queue. If the queue is full then the phrase will be lost. label can be a 16-bit array in order to build phrases dynamically. VOICE PLAY WAIT label Starts a voice speech in the same way as VOICE PLAY but it will continue the execution until all phrases in the queue have been spoken. label can be an 16-bit array in order to build phrases dynamically. VOICE WAIT Waits for the voice queue to be empty. VOICE NUMBER expr Causes the Intellivoice to say the given expression as a number. It works the same as with VOICE PLAY, meaning it will be placed at the end of the queue if the queue is not empty. VOICE phrases[,phrases] Data for phrases, use 0 to finish a phrase, for example: VOICE INIT VOICE PLAY WAIT numbers VOICE PLAY WAIT lets_play VOICE NUMBER 147 loop: GOTO loop numbers: VOICE ONE,THREE,SIX,HUNDRED,0 lets_play: VOICE LL, EH, EH, PA1, TT2, SS, PA2, PP, LL, EH, EY, PA2, 0 Allowed phrases are: PA5, PA4, PA3, PA2, PA1 MATTEL, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN, SIXTEEN, SEVENTEEN EIGHTEEN, NINETEEN, TWENTY, THIRTY, FOURTY, FIFTY, SIXTY, SEVENTY EIGHTY, NINETY, HUNDRED, THOUSAND, TEEN, TY, PRESS, ENTER, OR, AND AA, AE1, AO, AR, AW, AX, AY, BB1, BB2, CH, DD1, DD2, DH1, DH2, EH, EL, ER1, ER2, EY, FF, GG1, GG2, GG3, HH1, HH2, IH, IY, JH, KK1, KK2, KK3, LL, MM, NG1, NN1, NN2, OR2, OW, OY, PP, RR1, RR2, SH, SS TH, TT1, TT2, UH, UW1, UW2, VV, WH, WW, XR2, YR, YY1, YY2, ZH, ZZ FLASH INIT This should be the first thing called if you're using the FLASH functions. It only needs to appear once at the start of the program code. The default size is 16, equivalent to 128 rows of Flash memory. FLASH INIT SIZE constant_expression Same as FLASH INIT but sets the default size. A size of 1 will assign 8 rows for Flash memory (one erasable sector) A size of 2 will assign 16 rows for Flash memory (two erasable sectors) And so on. FLASH ERASE row Erases the row number specified by the expression. The row number can be any value between FLASH.FIRST to FLASH.LAST. It erases a >full sector< which is a multiple of 8 rows. So erasing any row in a multiple of 8 will erase the 8 consecutive rows. Note: You need to invoke IntyBASIC with --jlp command line option FLASH READ row,VARPTR #array(0) Reads the row number given by the expression and copies the content inside the given 16 bit array. This array must contain at least 96 values. The row number can range from FLASH.FIRST to FLASH.LAST. Note: You need to invoke IntyBASIC with --jlp command line option FLASH WRITE row,VARPTR #array(0) Writes the contents of an array of 16-bit values (the array must contain at least 96 elements) in the flash memory at the given row number. The row number can range from FLASH.FIRST to FLASH.LAST. Notice that it can write only to an >erased row<, this means that once a row is written it cannot be written to again until its sector is erased. Note: You need to invoke IntyBASIC with the --jlp command line option. Don't forget to use the option --jlp in jzintv and --jlp-savegame=file WARNING: YOUR INTYBASIC PROGRAM WILL TURN THE SCREEN BLACK AND STOP FOR A FEW MILLISECONDS WHILE THE JLP FLASH OPERATION IS PERFORMED, THIS INCLUDES ANY BACKGROUND MUSIC. DEF FN func = RAND % 10 DEF FN screen_off(row, col) = (row * 20 + col) DEF FN resetsprite(number) = SPRITE number,0 Allows to define functions with any number of arguments. Notice that these are processed like macros: The arguments are replaced as-is and the text of the function is inserted as-is after argument replacement. (because of that are included the extra parenthesis in the screen_off expression) For example, the two functions screen_off and resetsprite could be called as: A = func PRINT AT screen_off(4,8),"HELLO!" resetsprite(0) Please note that although it's possible to reuse internal function names, when called the internal functions have priority over DEF FN (DEF FN is ignored) STACK_CHECK This statement, if it appears anywhere in your program, will activate a sub-routine that will continuously check for stack overflow in the video interrupt routine. If the stack exceeds the allowed limit, the sub-routine will stop the program and show a prominent error message on the screen saying "Stack overflow”. This happens commonly when jumping to a PROCEDURE with GOSUB and getting out of the PROCEDURE with GOTO instead of RETURN. INCLUDE "filename.bas" Includes the contents of another source file inside the current IntyBASIC program. Notice that you cannot use INCLUDE recursively. Also, INCLUDE allows you to include external code anywhere in your program. You could even have half of a procedure in the main file and the rest of it in the included file. This is very useful for separating graphics and screen files. When looking for the file to include, the compiler will first look in the current directory and if the source file is not found there, it will look in the library path provided in the command line. CALL NAME Calls assembly function NAME without arguments. Note IntyBASIC will put the NAME all in uppercase. CALL NAME(expr) Calls assembly function NAME with one argument in R0. CALL NAME(expr,expr) Calls assembly function NAME with two arguments in R0 and R1 (up to 4 are allowed). ASM code Allows you to insert assembly code code directly into your source code. The line content is copied directly to output. It's also very useful to include assembly code modules, like this: ASM INCLUDE "yourfile.asm" >>>>>>>>>>>>>> Expression syntax The expression syntax is like a calculator. The usual precedence rules apply to expression operators. Addition and substraction have lower precedence than multiplication and division. This means 1 + 2 * 3 = 7 not 9. A=5 Decimal number A=$1000 Hexadecimal number A=&10101 Binary number #A=1.5 Fixed number (translated to $8001, note high byte is fraction) Note use of 16-bits variable A="C" Intellivision card code for letter A=B Simple assignment A=A+B Simple addition A=A-B Simple substraction #A=#A+.#B Fixed addition (note use of 16-bits variables) #A=#A-.#B Fixed substraction (note use of 16-bits variables) A=A*B Simple multiplication Multiplication by 2/4/8/16/32/64/128/256/512/1024/2048/4096 is internally optimized. Multiplication by constants less than 128 is optimized with macro. Multiplication uses a shift algorithm that is relatively efficient for most cases. (42 minimum or 702 cycles in worst case) Multiplication of variable by variable uses intvnut's fast multiply routine (fixed 272 cycles) When using --jlp switch the multiplication is accelerated by hardware A=A/B Simple unsigned division (done by repeated substraction, it can be slow) Division by 2/4/8/16/32/64/128/256 is internally optimized. Division of variable by variable uses my fast division routine (214 to 517 cycles) When using --jlp switch the division is accelerated by hardware A=A%B Simple unsigned remainder Notice that it calculates the remainder by repeated substraction (which can be slow) Remainder by powers of 2 internally uses AND. Remainder of variable by variable uses my fast remainder routine (214 to 517 cycles) A=(A+B)-C A=A AND B A=A OR B Notice this operation is not native, so it's not efficient A=A XOR B A=NOT A A=-A A=A=B If A and B are the same the result is $ffff (-1) else zero A=A<>B A=AB A=A<=B A=A>=B A=PEEK(expr) Reads a memory location PEEK always reads 16-bits data than can be processed in an expression. A=ABS(expr) Gets absolute value of expression (non-negative) A=SGN(expr) Gets sign of expression (-1, 0 or 1) A=array(expr) Accesses an array. The array can be defined with DIM or label for DATA array(expr)=A Writes data to an array. The array can be defined with DIM. DATA is not writable A=USR NAME Calls assembly function NAME (all in uppercase) without arguments. A=USR NAME(expr) Calls assembly function NAME with one argument in R0 A=USR NAME(expr,expr) Calls assembly function NAME with two arguments in R0 and R1 (up to 4 allowed) Assembly functions can put results in register R0. #A=VARPTR B Gets pointer to variable. Useful when linking assembler routines. #A=VARPTR C(0) Gets pointer to an array. Can be defined with DIM or label for DATA. CONT Contains AND'ed $01fe and $01ff complemented content (from both controllers) CONT.UP Non-zero if any controller pointing up CONT.DOWN Non-zero if any controller pointing down CONT.LEFT Non-zero if any controller pointing left CONT.RIGHT Non-zero if any controller pointing right CONT.BUTTON Non-zero if any controller button pressed. CONT.B0 Non-zero if any controller top buttons pressed (left/right) CONT.B1 Non-zero if any controller bottom left button pressed. CONT.B2 Non-zero if any controller bottom right button pressed. CONT.KEY Current pressed key (0-9 for numbers, 10-Clear, 11-Enter, 12-Not pressed) In any controller. Because movements can be taken as keys, it's suggested to wait for CONT.KEY to contain 12 before waiting for a key. CONT1 Contains complemented content of address $01ff (left controller) CONT1.UP Non-zero if controller pointing up CONT1.DOWN Non-zero if controller pointing down CONT1.LEFT Non-zero if controller pointing left CONT1.RIGHT Non-zero if controller pointing right CONT1.BUTTON Non-zero if controller button pressed. CONT1.B0 Non-zero if any of top controller buttons pressed (left/right) CONT1.B1 Non-zero if bottom left button pressed CONT1.B2 Non-zero if bottom right button pressed CONT1.KEY Current pressed key (0-9 for numbers, 10-Clear, 11-Enter, 12-Not pressed) Because movements can be taken as keys, it's suggested to wait for CONT1.KEY to contain 12 before waiting for a key. CONT2 Contains complemented content of address $01fe (right controller) CONT2.UP Non-zero if controller pointing up CONT2.DOWN Non-zero if controller pointing down CONT2.LEFT Non-zero if controller pointing left CONT2.RIGHT Non-zero if controller pointing right CONT2.BUTTON Non-zero if controller button pressed. CONT2.B0 Non-zero if any of top controller buttons pressed (left/right) CONT2.B1 Non-zero if bottom left button pressed CONT2.B2 Non-zero if bottom right button pressed CONT2.KEY Current pressed key (0-9 for numbers, 10-Clear, 11-Enter, 12-Not pressed) Because movements can be taken as keys, it's suggested to wait for CONT2.KEY to contain 12 before waiting for a key. Note using the .KEY syntax will include extra code inside IntyBASIC. also you should use WAIT for each .KEY reading because it's when IntyBASIC process debouncing and decodes keys. Remember this uses extra processor time. Useful information to avoid keys pressed to be processed as movements: c = cont2.button IF (c = $20)+(c = $40)+(c = $80) THEN GOTO skip_disc ' Ignore keys ...disc testing... skip_disc: CONT3 Contains complemented content of address $00ff (ECS left controller) CONT3.UP Non-zero if controller pointing up CONT3.DOWN Non-zero if controller pointing down CONT3.LEFT Non-zero if controller pointing left CONT3.RIGHT Non-zero if controller pointing right CONT3.BUTTON Non-zero if controller button pressed. CONT3.B0 Non-zero if any of top controller buttons pressed (left/right) CONT3.B1 Non-zero if bottom left button pressed CONT3.B2 Non-zero if bottom right button pressed CONT4 Contains complemented content of address $00fe (ECS right controller) CONT4.UP Non-zero if controller pointing up CONT4.DOWN Non-zero if controller pointing down CONT4.LEFT Non-zero if controller pointing left CONT4.RIGHT Non-zero if controller pointing right CONT4.BUTTON Non-zero if controller button pressed. CONT4.B0 Non-zero if any of top controller buttons pressed (left/right) CONT4.B1 Non-zero if bottom left button pressed CONT4.B2 Non-zero if bottom right button pressed COL0 COL1 COL2 COL3 COL4 COL5 COL6 COL7 Returns the collision status between sprites for the current frame. It is best to use these after WAIT. Don't forget to set the interaction bit in sprites (bit 8 of X-coordinate) bit 0-7 means collision against sprite number. bit 8 means collision against background pixel (pixel set) bit 9 means collision against borders RAND Produces a pseudo-random value between 0 and 255. The value produced is different on each video frame. RAND(range) Produces a pseudo-random value between 0 and range-1. The value produced is different on each video frame. Note that it's slower to generate, and the value will be generated faster if based on powers of 2. The maximum range value is 256. RANDOM(range) Produces a pseudo-random value between 0 and range-1. This forces the update of the random number (it doesn't need a WAIT to change). Notice that it's slower to generate, and the value will be generated faster if based on powers of 2. The maximum range value is 256. LEN(string) Returns the length of a string. Very useful in combination with DEF FN, for example, for creating strings centered on the screen. POS(expr) Returns the current screen position (useful for PRINT AT) The expression is analyzed but no code generated. FRAME Returns the current frame number (0-65535, it cycles back to 0 after reaching 65535) NTSC Returns 1 if the Intellivision is an NTSC console, otherwise returns zero. #MOBSHADOW(x) Use this to access elements in the MOB buffer (the place where SPRITE data is saved). The indexes 0 to 23 correspond exactly to the contents to be written to locations 0 to 23 of the STIC. #BACKTAB(x) Use this to access elements in the screen buffer (located at $0200-$02EF) FLASH.FIRST Returns the first readable/writable row of JLP Flash memory FLASH.LAST Returns the last readable/writable row of JLP Flash memory MUSIC.PLAYING Returns zero if music is not currently playing, returns a non-zero value otherwise. VOICE.AVAILABLE Returns a non-zero value if the Intellivoice module is detected, otherwise returns zero. VOICE.PLAYING Returns a non-zero value if the Intellivoice is currently playing samples, otherwise returns zero. ECS.AVAILABLE Returns a non-zero value if the Entertainment Computer System is connected, otherwise returns zero. The fixed numbers are useful to move game elements in fractional steps, the trick is to preserve the current coordinate in a 16 bits variable, and when using it for the final display you should copy the value to a 8 bits variable (cutting the fixed part) or use AND 255 or %256 as these are optimized for this purpose. More about the fixed numbers used in IntyBASIC: http://atariage.com/forums/topic/229168-now-available-intybasic-compiler-v08/page-2#entry3080617 >>>>>>>>>>>>>> Assembly language interfacing The USR expression and the CALL statement allow you to call assembly language modules from inside IntyBASIC programs. Note the label name for assembly language modules is translated to uppercase. IntyBASIC expect the following conventions to be preserved: Before calling: R0 = Value of first argument (or trash) R1 = Value of second argument (or trash) R2 = Value of third argument (or trash) R3 = Value of fourth argument (or trash) R4 = Trash R5 = Location to return After calling: R0 = Value from assembly language module (only USR expression) R1 = Not important R2 = Not important R3 = Not important R4 = Not important R5 = Not important If your module changes the address of the Stack Pointer (R6) or messes with previous values stored then there is a high probability that the IntyBASIC program will crash. If your function is relatively simple: ASM MYFUNCTION: PROC ASM ; ... your code... ASM JR R5 ASM ENDP If your function needs more registers or calls nested functions: ASM MYFUNCTION: PROC ASM BEGIN ; Really it's PSHR R5 ASM ; ... your code... ASM RETURN ; Really it's PULR R7 ASM ENDP >>>>>>>>>>>>>> Some further notes A program’s execution is sequential unless interrupted by GOTO or GOSUB. In any of your programs you should put GOTO at the end of the main block, otherwise execution could run in undesirable ways. For example: Example 1: A = 5 stop: GOTO stop ' Prevents BASIC running out of ROM Example 2: A = 5 stop: GOTO stop ' Prevents execution running inside procedure test: PROCEDURE END If you insert PROCEDURE, DATA, MUSIC or VOICE data in the middle of the execution sequence, the Intellivision processor will do strange things. So you must put your data at the end of the program or where the execution doesn't reach it. Example 3: A = 6 DATA 5,6,7 ' Bad, this gets executed! move it after the GOTO stop: GOTO stop Display starts in color-stack mode, each card of the 20x12 screen can have the bit 13 set to 1 so it avances current pointer to color-stack and changes the background color. In order to change the 4 color-stack predefined values, you should use this: MODE 0,1,2,3,4 ' Select blue color as initial color and load other 3 colors The color values are in the range 0-15. In order to select foreground/background mode, you should use this: MODE 1 By default, IntyBASIC starts the program at $5000 area. The available space goes up to $6FFF, for a cartridge binary of 16K. You can measure your program by checking the generated LST file created by the assembler or the CFG file. In any case, you can insert ASM statements to create bigger programs, like this: ASM ORG $D000 ASM ORG $F000 This way you can use the areas $D000-$DFFF and $F000-$FFFF. It's easier to manage and calculate available space if you put only data in these areas. Another way is to look into the generated .lst file, you can see what memory locations are used by IntyBASIC generated code. Using modern Flash cart and homebrew cartridge PCBs allows following addresses to be used without additional programming: $2000-$2FFF $5000-$6FFF $A000-$BFFF $C100-$FFFF As technical note, the use of any ECS feature inside your IntyBASIC program (such as SOUND 5-9, CONT3 or CONT4) will cause your program to boot from $4800 to disable the ECS ROM. This has the extra advantage of disabling the standard Mattel screen that can be seen a fraction of second before starting your program. >>>>>>>>>>>>>> Real number of variables allowed The number of 8-bits variables allowed are: 228 Substract 3 if you use SCROLL Substract 3 if you use VOICE Substract 6 if you use the keypad Substract 26 if you use PLAY The number of 16-bits variables allowed are: 47 (7962 if using --jlp or --cc3 switch) Substract 20 if you use SCROLL or 30 if you use VOICE Note each location of an array allocated with DIM counts as one variable. >>>>>>>>>>>>>> Generating ROM files for Nostalgia emulator By default the as1600 assembler generates a .bin/.cfg pair of files, both can be copied in the roms directory of the Nostalgia emulator for testing your programs. Alternately you can convert both files to a single .rom file, using the bin2rom utility included with jzintv: bin2rom game.bin It will generate a game.rom file that contains a mix of the .bin and .cfg file and it's more easy to test with Nostalgia. Another alternative is to use the following as1600 invocation to generate .rom file in the same run: as1600 -o output -l output.lst output.asm >>>>>>>>>>>>>> Source code debugging I've included enough information in the generated ASM file and with extensive help from intvnut there is now support for basic debugging with IntyBASIC source code shown along the way. You need to compile your program in this way: intybasic input.bas output.asm as1600 -j output.smap -s output.sym -o output.bin -l output.lst output.asm intysmap output.smap jzintv -d output.bin --src-map=output.smap --sym-file=output.sym After this you can use normally the jzintv debug commands. Notice that under Windows, your main window must be 160 columns or wider. Inside the debugger use the jzintv command >160 to expand the window if necessary. Also you can add useful metadata in your IntyBASIC code, like title of game, author name, license, date, etc. It will pass through the as1600 assembler, and it will get embedded into the final ROM file.. This information is used by the newest versions of the LTO-Flash software, and it can be read by the rom_metadata utility in the jzintv package. Some examples of these tags: ASM CFGVAR "name" = “A woman looks for her cat" ASM CFGVAR "short_name" = “Cat search!” ASM CFGVAR "author" = “Mindy Cat Lover” ASM CFGVAR "release_date" = "2018-07-20" ASM CFGVAR "license" = “public domain" ASM CFGVAR "music_by" = “Bea U. Ty” The latest reference to these metadata tags is available at http://spatula-city.org/~im14u2c/intv/jzintv/doc/rom_fmt/id_tag.txt >>>>>>>>>>>>>> Permissions in Mac OS X and Linux The compressed executables for both Mac OS X and Linux probably will not have the right permissions when uncompressed. So is suggested to run these commands in your IntyBASIC directory: chmod 755 intybasic chmod 755 intybasic_linux If your IntyBASIC directory is not in current path you can run it using this while at IntyBASIC directory: ./intybasic game.bas game.asm Also you can structure your IntyBASIC directories using the script intbas.pl provided by James Pujals (DZ-Jay), the structures required are the following: ============================================================================= FILE PATH: DESCRIPTION: ============================================================================= +-- intybasic Installation directory +-- bin IntyBasic binary distribution | |-- intbas.pl -> Helper script to compile/assemble | |-- intybasic_linux -> IntyBasic for Linux | |-- IntyBASIC.exe -> IntyBasic for Windows | |-- intybasic -> IntyBasic for Mac OSX | |-- intycolor -> IntyColor for Mac OSX | |-- intyColor.exe -> IntyColor for Windows | `-- intycolor_linux -> IntyColor for Linux | +-- examples BASIC sample program repository | +-- game1 Sample Project: game1 | | +-- bin AS-1600 assembler output | | | |-- game1.bin \_ Game binary in BIN+CFG format | | | |-- game1.cfg / | | | |-- game1.ls -> Assembler listing file | | | |-- game1.map -> Assembler memory map | | | |-- game1.rom -> Game binary in ROM format | | | `-- game1.sym -> Assembler symbol table | | | | | +-- asm IntyBasic compiler output | | | `-- game1.asm -> Generated assembly source | | | | | `-- game1.bas BASIC source file | | | `-- title | +-- bin AS-1600 assembler output | | |-- title.bin \_ Game binary in BIN+CFG format | | |-- title.cfg / | | |-- title.ls -> Assembler listing file | | |-- title.map -> Assembler memory map | | |-- title.rom -> Game binary in ROM format | | `-- title.sym -> Assembler symbol table | | | +-- asm IntyBasic compiler output | | `-- title.asm -> Generated assembly source | | | `-- title.bas BASIC source file | +-- games BASIC game program repository | `-- (empty) Add your own programs here. | +-- lib IntyBasic library modules | |-- intybasic_prologue.asm -> Prologue module | `-- intybasic_epilogue.asm -> Epilogue module | |-- manual.txt IntyBasic manual `-- INTBAS - README.txt This README file. You need to setup some environment variables: INTV_SDK_PATH = Pointing to the directory containing jzintv structure INTV_BASIC_PATH = Pointing to the installation directory (per structure) DZ-Jay mounted his own IntyBASIC distribution following that structure: http://atariage.com/forums/index.php?app=core&module=attach§ion=attach&attach_id=363028 >>>>>>>>>>>>>> Useful links jzintv emulator (including as1600 assembler) http://spatula-city.org/~im14u2c/intv/ Intellivision Nostalgia emulator http://www.intellivision.us/intvgames/nostalgia/nostalgia.php >>>>>>>>>>>>>> Acknowledgments Thanks to following members of Atariage for contributing valuable suggestions, test programs and even support libraries: Albert artrag atari2600land awhite2600 carlsson catsfolly ckblackm CrazyBoss Cybearg DZ-Jay First Spear freewheel GroovyBee intvnut Jess Ragan Kiwi mmarrero RevEng SpiceWare Tarzilla