Applesoft BASIC CMD
From: tdiaz-a(in_a_circle)-apple2-dotsero-org (Tony Diaz) Newsgroups: comp.sys.apple2,comp.answers,news.answers Approved: news-answers-request@MIT.EDU Followup-To: comp.sys.apple2 Subject: Applesoft BASIC Frequently Asked Questions (FAQ)
Archive-name: apple2/faq/part1 Posting-Frequency: monthly Last-modified: August 21 2007 Version: 0.27 URL: http://apple2.info/wiki/index.php?title=Applesoft_BASIC
The Applesoft BASIC FAQ
NOTE: this FAQ is in beta form, and is still being written. Expect a few minor continuing changes in its layout, content, and correctness. Most info should be correct-- I'd like to be notified of any problems noted in the FAQ.
This document attempts to give a detailed and correct set of answers about Applesoft BASIC, an interpreted programming language for the Apple II series of computers. It is also intended as a reference for commands and the like; it may at once time in the future include tutorials, but does not do so now.
DOS 3.3 and ProDOS command line commands are not included in this FAQ; they have a FAQ of their own at http://www.visi.com/~nathan/a2/faq/dos.html. I do cover some disk I/O from within Applesoft programs, however, in this FAQ.
Copyright (c) 1998-2007 by Tony Diaz (email: tdiaz-a(in_a_circle)-apple2-dotsero-org), all rights reserved. This document can be freely copied so long as 1) it is not sold, 2) any sections reposted elsewhere from it are credited back to this FAQ with the FAQ's copyright info and official WWW location (URL: http://apple2.info/wiki/index.php?title=Applesoft_BASIC) left in place.
This FAQ may not be sold, bundled on disks or CD-ROMs, reprinted in magazines, books, periodicals, or the like without prior consent from the maintainer, Tony Diaz. Exceptions are explicitly granted for Juiced.GS and _The_Lamp. Email me for permission otherwise.
Big thanks to Nathan Mates, the previous maintainer of this comp.sys.apple2 FAQ, for allowing it to live on after his departure and anyone who took up that mantle before him.
Disclaimer: I've tried to make this FAQ as accurate as possible, but there's the chance that it's not perfect. I apologize in advance for any slipups. Until I am confident that all information is 100% accurate, you are advised that you are following all info at your own risk. I will fix any problems found with this FAQ, but will not be held liable for the results of problems.
- 1 Section 8: Applesoft command reference by name
- 1.1 ABS(expr)
- 1.2 AND
- 1.3 ASC(expr$)
- 1.4 AT
- 1.5 ATN(expr)
- 1.6 CALL memaddr
- 1.7 CHR$( byte)
- 1.8 CLEAR
- 1.9 COLOR=num
- 1.10 CONT
- 1.11 COS( ang)
- 1.12 DATA const[,const...]
- 1.13 DEF FN var(arg)=expr
- 1.14 DEL line1,line2
- 1.15 DIM var(size1[,size2...])[,var2(size1[,size2]...)...]
- 1.16 DRAW shapenum [AT x,y]
- 1.17 END
- 1.18 EXP( expr)
- 1.19 FLASH
- 1.20 FN var(arg)
- 1.21 FOR varb = start TO end [STEP increment]
- 1.22 FRE(expr)
- 1.23 GET varb
- 1.24 GOSUB linenum
- 1.25 GOTO linenum
- 1.26 GR
- 1.27 HCOLOR=val
- 1.28 HGR
- 1.29 HGR2
- 1.30 HIMEM:val
- 1.31 HLIN x1,x2 AT y
- 1.32 HOME
- 1.33 HPLOT [TO] x,y [ TO x1,y1 [ TO x2,y2]]
- 1.34 HTAB x
- 1.35 IF expr ...
- 1.36 IN#slotnum
- 1.37 INT(expr)
- 1.38 INVERSE
- 1.39 LEFT$(expr$,num)
- 1.40 LEN(expr$)
- 1.41 LET var=expr
- 1.42 LIST [line1][,-][line2]
- 1.43 LOAD
- 1.44 LOG(expr)
- 1.45 LOMEM:
- 1.46 MID$(expr$,start[,len])
- 1.47 NEW
- 1.48 NEXT [varb1][,varb2...]
- 1.49 NORMAL
- 1.50 NOT
- 1.51 NOTRACE
- 1.52 ON expr [GOSUB|GOTO] line1[,line2...]
- 1.53 ONERR GOTO line
- 1.54 OR
- 1.55 PDL(n)
- 1.56 PEEK(addr)
- 1.57 PLOT x,y
- 1.58 POKE memaddr, byte
- 1.59 POP
- 1.60 POS(expr)
- 1.61 PRINT[expr][[;,]expr2...]
- 1.62 PR# slotnum
- 1.63 READ var1[,var2...]
- 1.64 RECALL varname
- 1.65 REM [comment]
- 1.66 RESTORE
- 1.67 RESUME
- 1.68 RETURN
- 1.69 RIGHT$(expr$,num)
- 1.70 RND(expr)
- 1.71 ROT= expr
- 1.72 RUN [linenum]
- 1.73 SAVE
- 1.74 SCALE= expr
- 1.75 SCRN(x,y)
- 1.76 SGN(expr)
- 1.77 SHLOAD
- 1.78 SIN(ang)
- 1.79 SPC(num)
- 1.80 SPEED= val
- 1.81 SQR(num)
- 1.82 STEP
- 1.83 STOP
- 1.84 STORE
- 1.85 STR$(expr)
- 1.86 TAB(xposn)
- 1.87 TAN(ang)
- 1.88 TEXT
- 1.89 THEN
- 1.90 TO
- 1.91 TRACE
- 1.92 USR(expr)
- 1.93 VAL(expr$)
- 1.94 VLIN y1,y2 AT x
- 1.95 VTAB val
- 1.96 WAIT memaddr,val1[,val2]
- 1.97 XDRAW shapehum [AT x,y]
- 1.98 (ampersand) & [parameters vary]
Section 8: Applesoft command reference by name
The absolute value of the expression.
Logical anding of two logical expressions, yielding 0 or 1. Applesoft treats 0 as false and any other number as true on input.
Returns the ASCII code for the first character in the string. If the first character has ascii value of 0, a '?SYNTAX ERROR' will occur. If the input string is a null string, a '?ILLEGAL QUANTITY ERROR' will occur.
Reserved word required in the middle of HLIN and VLIN statements, optional in the middle of DRAW and XDRAW.
Arctangent of the expression in radians. Results range from -Pi/2 to +Pi/2.
Calls an assembly language subroutine at 'memaddr'. [The subroutine should end with a 'RTS' instruction; no need to preserve register contents]
Converts a specified ascii value (must be in the range 0..255) to a string.
Dumps the contents of all variables from memory, effectively assigning a value of 0 to all integer and real values, and a null string to all strings. Also undimensions all arrays. Can be called from with a program, or at the command prompt.
Sets the Lores plotting color. Valid colors are 0 (Black), 1 (Magenta), 2 (Dark Blue), 3 (Violet), 4 (Dark Green), 5 (Dark Gray), 6 (Medium Blue), 7 (Light Blue), 8 (Brown), 9 (Orange), 10 (Light Gray), 11 (Pink), 12 (Bright Green), 13 (Yellow), 14 (Aqua) and 15 (White). If the value for your color is greater than 15, only the remainder when divided by 16 is used, so 'COLOR=16' is equivalent to 'COLOR=0' and the like.
Immediate-mode command to attempt to continue running a program after it was stopped by STOP, END or a Control-C. You cannot continue after Control-C'ing an INPUT statement, no program was running, or the program has been modified since stopping.
Computes the cosine of ang, with ang measured in radians.
Stores a list of constant values to be assigned by READ. Values can either be numeric or strings; quotes are not needed unless the string contains spaces, commas or colons. Constants can be blank (i.e. nothing between the commas), leading to a zero (if read as numeric) or a null string.
DATA statements are essentially ignored in immediate mode; strange behavior has been occasinally observed if program flow reaches them.
DEF FN var(arg)=expr
Defines a mathematical function of at most one line for later use as 'FN var(arg)'. 'arg' is a placeholder variable name; it can be used in expr to pass variables in. However, 'arg' can be used elsewhere in the program without worrying about side effects from function definition or calls. Functions can call other functions, but may not be recursive.
Functions may be redefined if desired with another DEF FN block.
Deletes a line or range of lines. Line2 must be greater than or equal to line1; all lines between them (inclusive) are deleted. It can be used in deferred mode under Applesoft, at which point the lines are deleted and the program stops, no possibility of a CONT.
To delete a single line of code from the prompt, you can type simply the line number and press return-- that 'replaces' it with an empty line.
Creates space for an array of the specific type (real, integer or string) and the specific size. n+1 elements in each dimension are created, referenced 0..N. Given that Applesoft only has a limited memory pool, you cannot create very large arrays. Multiple arrays can be DIM'd at once by separating them with commas in the DIM statement. If an array is referenced before being DIM'd, Applesoft assigns the array a size of 10. You may not DIM an array a second time.
DRAW shapenum [AT x,y]
Draws the hires shape specified in the current HCOLOR, SCALE and ROT on the current hires screen. The position is optional; if omitted, it defaults to the last point done by the last DRAW, XDRAW or HPLOT.
Drawing shapes when no shape table has been defined or loaded is a bad idea.
Stops the currently running program, leaves variables intact.
Raises e (2.71828183...) to the specified power.
Sets future output from PRINT statements to flash on the 40-column text screen. Not easily available in 80-column modes.
Several to all of ProDOS's BASIC.SYSTEM versions went into TRACE mode if your code had a 'THEN FLASH' evaluated.
Executes the named function (previously defined with DEF FN and arguments.
FOR varb = start TO end [STEP increment]
This sets up a loop. You can only loop over reals; the increment defaults to 1 unless specified. The loop stops when 'varb' is greater than 'end' if 'increment' is positive, or less than 'end' if 'increment' is negative. The counter variable 'increment' can be zero, in which case this is an infinite loop. It is legal to modify the loop variable in the middle of a loop. The contents of a FOR loop are always executed at least once, since it only exits from the NEXT statement.
In addition, the start, end and increment parameters are evaluated only once, at the start of the loop, so any changes to them will not be reflected.
If expr is not zero, this returns the amount of free memory is available to Applesoft. [If the return value is greater than 32767, will return the 2's complement value; add 65536 to the value to get the correct value.] FRE(0) forces a garbage collection of unused strings from the memory pool; it may be fairly slow at times.
GET only waits for one character, and returns immediately on getting that without printing it to the screen. Thus, 'GET A$' is an excellent way of waiting for any key, or building a better INPUT, etc. GETting a real or an integer is not really recommended-- if the user types a non-numeric character (0-9, +, -, ,, E, etc), the program will stop with an error.
Saves the current position within the code, and branches to linenum, which must exist. With a RETURN, you can go back to the original position, or use POP to 'forget' the most recent gosub return address. There is a limit of 24 nested GOSUBs, though active FOR loops and an error handler will reduce this.
Branches program execution to the specified line, an error if the line doesn't exist.
Sets the screen to Mixed Lores graphics mode (40x40+4 lines of text), and sets the top 40 graphics rows (20 text screen lines) to all black.
Sets the color used for Hires graphics drawing. Valid colors are 0 (Black 1), 1 (Green), 2 (Violet), 3 (White 1), 4 (Black 2), 5 (Orange), 6 (Blue), 7 (White 2).
Turns on the first hires screen to a mixed 280x160 mode with 4 lines of text at the bottom, and clears the graphical section to all black. Does not move the cursor or set a 4-line text window like GR does.
Turns on the second hires screen, and clears it to black. It also displays all of it (280x192) with no text visible at the bottom. [There's no easy way to get both the second hires screen and 4 lines of text onscreen in a "mixed" mode as with lores and the first hires screen without some loops to do memory copying and the like.]
Sets the highest memory position available for Applesoft's variables. Used to reserve some space off for binary program code and the like. The ':' is part of the command; if you do 'HIMEM=x', you will set the real variable HI. The himem position is normally set by default; only mess with it if you know what you're doing; under ProDOS it should be an even multiple of 1024 (1K).
ProDOS's BASIC.SYSTEM grabs space on the fly for things, so moving HIMEM under ProDOS may be a risky job. In all cases, it must be a multiple of 256 under ProDOS.
HLIN x1,x2 AT y
Draws a horizontal line on the lores graphics screen from x1,y to x2,y. x1 and x2 do not need to be in sorted order. x1, x2, and y should be within the limits of the lores graphics screen (0..39 for x, 0..47 for y), or the results may be unpredictable.
Clears the text display screen and positions the cursor in the top-left. Note that when in Lores mixed mode (40x40+4), the text screen consists of only 4 lines of text. Use the TEXT command to exit the graphics mode.
HPLOT [TO] x,y [ TO x1,y1 [ TO x2,y2]]
Draws a point, line, or series of line segments. If only a single point is specified, it is drawn. With a TO, a line segment is drawn from the last drawn point to the new location. Use HCOLOR= to set the color of the line before drawing.
Sets the cursor's horizontal position to x. Under 80-column modes, you may find that 'POKE 1403,x-1' works more reliably. [Htab uses 1-80 to set the column; the POKE uses 0-79]
IF expr ...
Expression expr is parsed, and if true (not zero), then the rest of the line is parsed. If expr is false (logical and numeric zero), then control skips to the next line of code. No parentheses are needed around the x clause, but they don't really hurt. There is no else clause in the language, but it is easy to get around that. 'IF x THEN GOTO n' can also be written as 'IF x GOTO n' or 'IF x THEN n', but this abbreviation can only be done for 'THEN GOTO', no other statements.
Several to all of ProDOS's BASIC.SYSTEM versions went into TRACE mode if your code had a 'THEN FLASH' evaluated.
Accepts input from the specified slot, 0..7. Slot 0 is not a real slot for input here, so it defaults to the keyboard. However, when running under DOS 3.3 or ProDOS, you should use the DOS command version of this, namely 'PRINT CHR$(4)"IN#"slot'
== INPUT ["prompt";]var[,var2...]
This can get integers, reals, and strings, as well as getting several at once. The prompt string is printed before user input is gotten. Multiple variables can be entered at once, separated by commas or returns.
Returns the largest integer less than or equal to the input value.
Sets future output from PRINT statements to appear in reverse video (background on foreground color).
Returns the leftmost 'num' (num=0..255) characters of the string, if num is larger than the length of the input string, the input string is the result.
The length of the string.
Sets a variable. The 'LET' is redundant, though it may be used for readability.
Displays the program specified. If no options are given, it lists the entire program. If followed by one line number, it lists just that line. Using a line number followed by a comma or a hyphen lists all lines starting at that point. Using a comma or hyphen followed by a line number lists all lines to that point. Using two line numbers separated by a comma or hyphen lists all lines between the two, inclusive.
'LIST 0' will list all lines in the program, not just line 0.
Attempts to load a program off the cassette port, if available. Mostly outdated now; the //c, IIc+ and IIGS don't have a cassette port, so this command does nothing.
The natural logarithm (base e) of expr, for expr>0. To get the common (base 10) logarithm, use 'LOG(expr)/LOG(10)'
Sets the lowest memory position available for Applesoft's variables. Used to reserve some space off for binary program code and the like. The ':' is part of the command; if you do 'LOMEM=x', you will set the real variable HI. The value is normally set by default; only mess with it if you know what you're doing.
Returns 'len' (1..255) characters starting at 'start' (1..255) characters from the left edge of the string. If the 'len' parameter is omitted, returns to the end of the string; if 'start' is larger than the size of the string, returns a null string.
Clears any Applesoft program and all variables from memory. Not easily undoable, so be careful what you do.
Updates a loop started with a FOR. The loop's variable is updated by the appropriate amount, and if the loop is to continue, program flow goes back to the top of the loop. The specification of the variable is optional-- if omitted, Applesoft will use the innermost active loop to deal with. Multiple loops can be terminated with a single NEXT-- 'NEXT J,I' is equivalent to 'NEXT J: NEXT I'
Sets future output from PRINT statements to appear in normal video (foreground on background color).
Logical negation. 0 becomes 1, anything non-zero becomes zero.
Stops any program flow tracing set up by TRACE.
ON expr [GOSUB|GOTO] line1[,line2...]
Sets up a GOSUB or GOTO to a series of lines listed depending on the expression, which must have resulting value 0..255. The program branches to the first listed line number if the result is 1, the second if 2, and so on. If the result is 0 or a value higher than the number of listed lines, program flow goes to the next instruction after this ON-GOSUB or ON-GOTO.
ONERR GOTO line
Registers a function to GOTO when an error occurs. ONERR GOTO must be executed before the error happens. When the specified function is called, PEEK(222) contains the error code. To attempt recovery from where the problem started, use RESUME.
Due to a bug, if you wish to safely use RESUME to go back to loops, subroutines, and the like, you should POKE the following values someplace in memory (they're relocatable, so the address doesn't matter) and CALL the subroutine before RESUMEing: 104, 168, 104, 166, 223, 154, 72, 152, 72, 96. This cleans up the stack to what it should be.
Logical oring of two logical expressions, yielding 0 or 1. Applesoft treats 0 as false and any other number as true on input.
Returns the value based on the position of the analog device numbered 0 to 3. n=0 for the first paddle or the horizontal axis of a joystick, n=1 for the second paddle or the vertical axis of a joystick (n=2,3 for the third and fourth paddles or second joystick). PDL() returns a value between 0 and 255; the 'center' is approximately 127. There should be a slight pause between calls to PDL to allow the hardware time to recover from the analog reading and prepare for another. A quick FOR-NEXT loop does the job nicely: 'XP%=PDL(0): FOR PD=1 TO 10:NEXT: YP%=PDL(1)'
Returns the contents of the memory byte #addr in decimal. addr must be in the range -32768 to 65535. [Memory addresses less than zero have 65536 added to them to get the real address]. Randomly PEEKing around memory is a bad idea.
Sets the specified point on the Lores graphics screen (x=0..39, y=0..47) to the currently set COLOR. If the lores screen is not on, you will affect the text screen.
POKE memaddr, byte
Stores byte (0..255) into the specified memory address. Don't POKE randomly; you can cause bad things to happen.
Disposes of the last RETURN address, effectively changing the most recent GOSUB to a GOTO.
Ignores expr, returns the horizontal position of the cursor, from 0 to 39. In 80-column mode, this always returns 0.
Sends characters to the current output device. PRINT will print string constants ('PRINT "HELLO"'), numeric constants and expressions ('PRINT 2+2'), strings ('PRINT NAME$'), reals ('PRINT FOO'), or integers ('PRINT SP%'). It can also print several of these at once if semicolons (';') or commas are between the sections: 'PRINT "The Answer:"; 2+2'. Semicolons are not really needed before the start of a string constant or after them-- 'PRINT D$"CLOSE"' is perfectly legal.
If a semicolon is present at the end of a PRINT statement, the 'default' of a concluding carriage return is surpressed. 'PRINT's are not really buffered-- they appear as soon as ready, even if the trailing carriage return is surpressed. If a PRINT exists by itself, it will print a 'carriage return' and go to the left edge of the next screen row, scrolling if necessary. A comma present separating items jumps to the next 'tab' stop, which are located 16 columns apart at columns 1, 17, 33, etc. The second tab stop exists only if column 16 for that line is empty (i.e. filled with spaces), and the third only if columns 24-32 are empty.
For floating-point values, scientific notation is used for values with absolute value less than 0.01 or if there are more than 9 digits in front of the decimal point.
'PRINT's of numeric values are always left-justified, and the output will take up however much space is needed to represent it. Strings similarly take up as much room as necessary and no wordwrapping is done. No print formatting for other forms is built in; you'll have to write your own if this is needed.
'PRINT' can be abbreviated as '?' when entering programs.
Sends output to the specified slot, 0..7. Slot 0 is not a real slot for output, so it defaults to the 40-column text screen. However, when running under DOS 3.3 or ProDOS, you should use the DOS command version of this, namely 'PRINT CHR$(4)"PR#"slot'
Reads the next available item(s) from a DATA statement into the specified variables. It is sequential access only, travelling through the list from the first items in the first DATA to the last. See also RESTORE.
Attempts to load an array off the cassette port, if available. Mostly outdated now; the //c, IIc+ and IIGS don't have a cassette port, so this command does nothing.
Marks the start of a comment. Any and all text following it to the end of the line is treated as a comment, and will not be executed.
Moves the DATA pointer back to the first DATA statement, so that following READs will get data from there.
Attempts program recovery at the point where an error occurred, but was caught with an ONERR GOTO. Do not use if no error has occurred.
Moves program flow back to just after the most recently executed GOSUB. See also POP.
Returns the 'num' rightmost characters in the input string. If num is greater than the length of the input string, the entire string is returned.
Returns a pseudo-random number based on the value of expr. If expr=0, the last-returned random number is returned, If expr>0, then the result is in the range 0<=RND(expr)<1. If expr<0, the random number generator is seeded based on expr; subsequent calls with expr>0 will return the same sequence.
Sets the rotation value for hires shapes. Rot 0 is normal, 16 is 90 degrees clockwise, 32 upside down, and 64 is normal again. For SCALE=1, the only available rotation values are 0, 16, 32 and 48; SCALE=2 yields 8 positions, etc.
Clears all variables, and starts execution from linenum, if specified, otherwise from the lowest numbered line.
Attempts to save a program to the cassette port, if available. Mostly outdated now; the //c, IIc+ and IIGS don't have a cassette port, so this command does nothing.
Sets the scaling value for hires shapes. 1 is normal size, 2 is twice normal size, and the like, up to a maximum of 255.
Returns the color (0..15) of lores graphics screen pixel x,y. In text mode, returns part of the ascii value for the character at x,y/2.
There is no corresponding Applesoft function for the Hires screen.
Returns -1, 0, or 1, depending on whether the input number was negative, zero, or positive, respectively.
Attempts to load a Hires shape table off the cassette port, if available, and sets the shape table pointers. Mostly outdated now; the //c, IIc+ and IIGS don't have a cassette port, so this command does nothing.
Computes the sine of ang, with ang measured in radians.
Print num blank spaces; this statement may only be used inside a PRINT statement. Faster than a FOR-NEXT loop.
Sets the text output speed. 255 is the fastest, 0 is the slowest.
Computes the square root for num>=0, and an error if num<0.
Please see the FOR statement for use.
Halts program execution, notifying the user which line the program stopped at. Use CONT to continue, assuming no changes have been made to the program's code.
Attempts to store an array to the cassette port, if available. Mostly outdated now; the //c, IIc+ and IIGS don't have a cassette port, so this command does nothing.
Converts a numeric value to a string, using the same formatting as used by PRINT.
Used inside a PRINT statement, and moves the cursor right to column 'xposn' if the current position is left of xposn, does not move the cursor if the current position is right of xposn.
HTAB is normally used instead.
Computes the tangent of ang, with ang measured in radians.
Switches the display to text mode, full screen (40x24 or 80x24), and moves the cursor to the bottom row of the screen. If Lores graphics were just on, the top 20 lines of the screen may be filled with garbage. Use HOME to clear them off.
See syntax details under IF.
Used as part of FOR and HPLOT; see syntax there.
Displays the line number for each statement as it is executed. Multiple statements on a line may cause that line to be displayed several times. Use NOTRACE to cancel. Since DOS 3.3 commands from within a program require a return (CHR$(13)) before the DOS command, the trace line numbers can interfere with this.
Jumps to memory location $0A (which can contain a JMP to wherever you want); the return value is whatever the floating point accumulator held on returning.
Converts the first number found in string to a numeric value, returning 0 if there is no number in the string.
VLIN y1,y2 AT x
Draws a vertical line on the lores screen from x,y1 to x,y2 in the currently set COLOR. y1 and y2 do not need to be in sorted order. If the lores screen is not active, garbage may appear on the text screen. x, y1, and y2 should be within the limits of the lores graphics screen (0..39 for x, 0..47 for y), or the results may be unpredictable.
Sets the cursor's vertical position on the screen. 1 is the top row on the screen, 24 is the bottom.
Goes into an uninterruptable loop (except by control-Reset) looking at a memory address. The contents of memaddr are bitwise AND'd with val1, and compared to val2 (or 0 as a default). If the two are identical, then it keeps looping, else it exits.
XDRAW shapehum [AT x,y]
Erases the hires shape specified in the current HCOLOR, SCALE and ROT on the current hires screen. (Technically, it draws in an opposite color from the current pixel on the screen) The position is optional; if omitted, it defaults to the last point done by the last DRAW, XDRAW or HPLOT.
Drawing shapes when no shape table has been defined or loaded is a bad idea.
(ampersand) & [parameters vary]
Jumps to a vector at $3F5 (1013); machine language programs may use this as a hook to calling them. Smarter programs can be passed parameters; the exact syntax for those depends on the program.
There are a lot more questions with answers not included directly in this FAQ; please see http://apple2.info/wiki/index.php?title=CSA2_FAQ for more of them.
Copyright 1998-2007 by Tony Diaz