Commodore‎ > ‎BASIC‎ > ‎Keywords‎ > ‎


Keyword Abbreviation Token (hex) Version(s) Classification
STASH S{Shift+T} FE 1F 7.0 Command and Statement

STASH byteCount , systemAddress , externalAddress , externalBank
Parameters Type Legal Value(s) Default Value Note(s)
byteCount Unsigned Integer 0 ~ 65535 0 acts like 65536
systemAddress Unsigned Integer 0 ~ 65535    
externalAddress Unsigned Integer 0 ~ 65535    
externalBank Unsigned Byte  0 ~ 15     
Memory export.  Save system RAM to an external "RAM Expansion Unit".

STASH is used to save data from the system into a special cartridge with a DMA controller.  This was desgined for Commodore's 1700, 1750, and 1764 devices; each known as an REU (RAM Expansion Unit).  Some other devices, like the 1541 Ultimate, also have a compatible DMA controller.  Other RAM expansions devices (without a DMA controller), like GeoRAM, will not work with this command.
The C128 must have the CPU running at SLOW speed for this to work correctly.
The byteCount specifies the number of bytes to store.  A value of 0 specifies 65536 bytes for most devices (rarely useful).
The systemAddress is a 16-bit address inside the host computer.  The "system bank" is not given in this command; use the BANK command to set the desired bank inside the computer.  Note the original ROMs of the C128 (start-up says copyright 1985) do not set the correct RAM bank, although it does set the correct I/O and ROM configurations.  However, saving data from I/O registers is not reliable.
The externalAddress is a 16-bit address in the R.E.U., and forms the "low word" of the starting address in the R.E.U. where that data will be stored.  The externalBank is a 4-bit "bank" in the R.E.U. and forms the "high word" of the starting address in the R.E.U.  The STASH command limits externalBank to a maximum of 15, so the largest REU this supports is 1 MiByte.
The CPU is disabled while R.E.U. performs the transfer.  This means interrupts (for video events and RS-232 communication) will be delayed.  The R.E.U. is so fast, however, that unless you transfer a large number of bytes the saving will seem instant.  Of course what seems instant for a human may be a long time for a computer, so it may cause problems in some cases.
While transferring data, the REU's address can wrap from one bank to the next; however the wrap from the last bank back to the first bank is not reliable.
While transferring data, the REU updates the address where data is retrieved inside the computer, however it can not wrap the computer's BANK.
If no REU is connected, the command will usually silently succeed.  However, it is possible that some other cartridge device that uses the same registers as an R.E.U. would see the command and result in other behavior.
If any of the parameters are omitted, or if they are an invalid expression, SYNTAX ERROR occurs.  If any parameter is a string expression, TYPE MISMATCH ERROR occurs.  Floating-point values are converted with INT.  If the result is not a Legal Value (see table above) then an ILLEGAL QUANTITY ERROR occurs.
It is generally safe to save from any address in the computer (any systemAddress).  The only possible exception would be the I/O region where some chips will perform an action when they are read (for transfer into the REU).  In fact, you can save RAM into the REU that is normally impossible to access.  Like RAM at address 0 and 1, or for the C128, the RAM under the MMU "permanent" registers ($ff00 ~ $ff04).
The externalAddress and externalBank are also not critical.  Usually if you specify an address that doesn't exist in the R.E.U., the address will wrap-around to a valid value.  Of course you need to remember where data is stored in the R.E.U. in order to successfully read it back later.  This is totally up to the programmer/user.
Unfortunately saving a BASIC program is not simple.  You need to PEEK the secret variable "End of Text" (and possibly "Start of Text") if you want to only save the RAM used by the program.  It is okay (but inefficient) to save more bytes than used by the program in system RAM.  Remember the systemAddress for the start of the BASIC program will vary depending on whether a VIC/TED bitmap has been allocated or not. 
Assuming you don't have buggy ROMs, saving variables is also possible.  This is only practical with non-string variables.  You don't need to PEEK secret variables however (you can if you like) because there is the POINTER function.  It will tell you the address (in BANK 1) where a variable is currently located.  You can use that to save one or more variables (even an array) into RAM.
Example (for C128):
BANK 0 : REM save from bank 0

STASH 512,3584, 0,0 : REM save sprites to REU address 0, bank 0

STASH 32768,7169, 512,0 REM stash 32K of BASIC program to REU address 512, bank 0

BANK 1 : DIM A(9,9) : REM save from bank 1, create floating array 10x10

STASH 500,POINTER(A(0,0)), 0,1 : REM save array to REU address 0, bank 1

  Compare With  
  Contrast With  
  See Also  

© H2Obsession, 2014