Sie sind auf Seite 1von 13

----------------------------------------------------------------------------CrASH programmer's Guide! -----------------------------------------------------------------------------=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- IMPORTANT -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=TASM is required to program for CrASH. Download it from: http://www.ticalc.org/pub/dos/asm/tasm301.

zip This deals with Metacommands of TASM: CrASH programs must start with ".INCLUDE CRASH82.INC" There is no need to address a .ORG at the beginning of a program. There is no need to place a .END at the end of a program. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=----------------------------------------------------------------------------Contents ----------------------------------------------------------------------------Introduction Differences from ASH 3.0 A Guide to the ROM_CALLs A Guide to the CrASH calls Some Notes of Caution Installing an Interrupt Handler ----------------------------------------------------------------------------Introduction ----------------------------------------------------------------------------Hello, programmers! Programming in assembly for the TI-82 is just like programming for any other TI calculator. Because there are so many of you coding for TI-85's ZShell, we have tried to make adapting to CrASH very simple, by using all of the same ROM_CALL names. We hope that this will help current or former ZShell programmers in this new environment. Since CrASH relocates its programs when running, some parts may even be more simple to program than ZShell. CrASH is VERY simple to learn if you have programmed for the TI-82 before, in either OS-82/OShell-82 or ASH. CrASH is most similar in programming to ASH. The primary difference between 85/86 programming and the 82 is how the display is accessed. As you already may know, the screen is smaller (96x64 instead of 128x64), but this is NOT the only difference. The most important difference is that the display is accessed through a port, instead of through a memory map like the 85 and 86 use. It is not necessary for you to know how to access this port. The easiest way to display stuff is to use the GRAPH_MEM area as if it were the memory-mapped area of the 85/86 (except being smaller of course), and then using CR_GRBCopy (a CrASH-specific call) to do the port manipulation for you to display GRAPH_MEM. In order to make programming easier, CrASH supports usage of commonly used rom procedures, using the ROM_CALL macro. The commonly used functions are listed inside CRASH82.INC. There are some functions built into CrASH which are also listed inside CRASH82.INC. This includes a very fast display routine.

If you cannot understand the example listed below, it would probably be to the best of your interests to begin by learning assembly language. There are many sources from which to learn assembly language, and we may even release a tutorial ourselves in the future. Because the calculator needs to always move variables around in memory, assembly programs were truly difficult to write. To ease this problem, after the user selects a program, CrASH performs a simple relocation routine and moves the program to a fixed position in user memory. This means that you may address variables and labels INSIDE your own program. Note that this differs from OS-82 and ZShell - you do NOT add (PROGRAM_ADDR) every time you want to address something in your program. For example: .INCLUDE CRASH82.INC .DB "Hello World", 0 LD HL, $0000 LD (CURSOR_POS), HL LD HL, HelloString ROM_CALL(D_ZT_STR) JP AfterText HelloString: .DB "Hello world!", 0 AfterText: CALL CR_KHAND RET This loads the pointer to point to The JP after the D_ZT_STR allows you you experienced coders out there may has been coded, and you're right, so HelloString, so D_ZT_STR can display it. to jump over the String data. Some of be laughing at how terribly this program don't use it! ; The Only file CrASH program needs to start ; ALL CrASH programs must have a long name ; Set cursor to top-left ; Point to HelloString ; Jump to after the string

; Call uncrashable keyboard handler

There are several addresses in memory where you can store temporary data. Inside the include file, they are defined as FREE_A1, FREE_A2, FREE_A3, FREE_B, and FREE_C. FREE_A1 is actually the GRAPH_MEM, which can be used as free memory. FREE_A2, which is TEXT_MEM, can also be used as free memory. FREE_A3 should be safe to use unless the OPX variables are being used by a ROM_CALL function that is unknown. FREE_B is actually TEXT_MEM2, which CrASH will clear if you use CR_KHAND. FREE_C is actually APD_BUF, which may be being used by an interrupt. If you know the amount of memory needed, check to see if it fits before running the program, by reading APD_FREE (integer). Information on this is in the section titled "Some Notes of Caution". At startup, CrASH will always initialize the GRAPH_MEM, TEXT_MEM, CURSOR_X, CURSOR_Y, CURSOR_ROW, CURSOR_POS, and all general registers (A, B, C, D, E, H, L, IX) to 0. CrASH will also enable interrupts, and initialize the LCD Controller Port (for use with CR_GRBCopy). To convert the OBJ files produced by the assembler to the 82P files which the link program handles, use the DOS program CrPRGM82.EXE (which is included in the CrASH.ZIP archive). Included also is CrAsm.BAT, a small batch file that will process an assembly language file and automate the process to give you an 82P file. ----------------------------------------------------------------------------Differences from ASH 3.0 ----------------------------------------------------------------------------The main differences between CrASH and ASH are as follows:

Using the APD_BUF -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=In an effort to make interrupt handlers easier to write, CrASH includes a simple method of interrupt handling programs that run even when the program that started it is no longer loaded (IE Game Wizard) telling the other programs that APD_BUF is in use. It is VERY IMPORTANT that your programs pay attention to this information. If you absolutely MUST use APD_BUF, simply have your program refuse to run if not enough space is available in APD_BUF. The KEY_HAND replacement -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=In ASH, as many users AND programmers already know, you will crash your calculator if you turn off the calc during what is known as a KEY_HAND - the "normal" keyboard input routine used by TI-OS. CrASH has a method to program around this. The problem is that when any shell relocates a program to run it, memory is in an unstable (TI-OS doesn't know how to handle it) state. Exiting to TI-OS in this state will not crash immediately, but it will soon. ASH didn't have a way to counteract this. CrASH does, and this is in fact the original reason why we wrote CrASH. The way around is fairly simple. Relocate everything back, call KEY_HAND, and then rerelocate and return to the program. Fortunately, you don't have to code this. A built-in CrASH routine does this for you. Simply call CR_KHAND instead of KEY_HAND. There IS a downside - TEXT_MEM2 (shadow) is deleted as part of CR_KHAND. If you find this unacceptable, then just write your own key handler that doesn't use CR_KHAND - GET_KEY isn't very hard. See CrASH-specific calls for more information. Unlike most calls you do in TI-82 assembly, you do NOT use ROM_CALL to access CrASH calls. This is simply because CrASH call addresses don't vary depending on ROM version like ROM calls do. The Easy Random Call -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=To help keep program sizes down and make them faster, a simple random number routine has been added to CrASH. It's very simple to use. Call RAND, and it will return a 7-bit number in A (0-127). See CrASH-specific calls for more information. Compare HL with BC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=To help keep program size down (again), and for programmer convenience, we made a routine that compares HL with BC, in a matter identical to CP_HL_DE. Fortunately, CP_HL_DE is not a ROM_CALL, so you don't have to remember that CP_HL_DE is part of ROM and CP_HL_BC is part of CrASH. "Boss Key" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="Boss key" features are simply a method of exiting your program immediately to TI-OS so that you look like you're doing something important to your "boss". Of course, the person who you'll use it with is usually a teacher, not a boss. Anyways, returning to TI-OS directly has the exact same problems as KEY_HAND, so a workaround has been made. If you want your program to have a "boss key", simply return to TI-OS with the EXIT_2_TIOS CrASH routine. You may either CALL or JP to this routine - it does not matter. Of course,

EXIT_2_TIOS does not return, so you don't need a RET after the JP :) Large Programs -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Theoretically, CrASH programs can relocate as long as there is enough memory for that program to store itself on the calculator. The calculator does not crash after running like it did in ASH for programs that are even about 27 Kbytes. K_RIGTH -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=The name has been spelled correctly in CrASH. K_RIGTH included also for compatibility. Program names -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=The last, and most insignificant, change is in the naming of programs. ASH programs are usually named with "TI-OS valid" names so you can run them directly if you want. However, since CrASH does not have this capability, we changed that. All CrASH programs normally have a lowercase inverse A (as in the 85's lowercase alpha lock) at the beginning, to signify that they are assembly programs and to move them to the bottom of the program list.

----------------------------------------------------------------------------A Guide to the ROM_CALLs ----------------------------------------------------------------------------The names were mostly taken from the ZShell function names. LD_HL_MHL CP_HL_DE UNPACK_HL STORE_KEY GET_KEY CLEARLCD CLEARTEXT SCROLL_UP D_HL_DECI D_ZT_STR D_LT_STR D_ZM_STR D_LM_STR TR_CHARPUT TX_CHARPUT M_CHARPUT

Memory Addresses and Bits for Text Operations -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=(CURSOR_ROW) = Row to put character in (Y-coordinate) (CURSOR_COL) = Column to put character in (X-coordinate) SET 3, (IY+$05) = Display inverted (White on Black) RES 3, (IY+$05) = Display normally (Black on White) SET 1, (IY+$0D) = Alter text memory with writes RES 1, (IY+$0D) = Don't alter text memory with writes Memory Addresses and Bits for Mini Font Operations

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=(CURSOR_X) = x coordinate (CURSOR_Y) = y coordinate RES 1, (IY+$05) = Display only 6 rows of the character SET 1, (IY+$05) = Display the entire 7 rows of the character RES 3, (IY+$05) = Display character over the current screen SET 3, (IY+$05) = XOR character with the current screen ----------------------------------------------------------------------------CALL LD_HL_MHL ----------------------------------------------------------------------------Inputs: HL = Pointer to memory offset Returns: HL = (HL) (the word pointed by HL) A = L LD_HL_MHL places the word pointed to by HL into HL. This is useful when you have a table of word and you want to retrieve a word from it. Example: LD HL, Table LD DE, Offset ADD HL, DE ADD HL, DE CALL LD_HL_MHL ; ; ; ; ; HL points to a table defined by user DE is offset Add DE to HL twice -- This will get us the word offset (words are 2 bytes) HL now contains the word we looked up in the table

----------------------------------------------------------------------------CALL CP_HL_DE ----------------------------------------------------------------------------Inputs: HL and DE = The words to compare Returns: Updated flags CP_HL_DE compares HL and DE, just as if you had used the CP instruction. Example: LD HL, (Score) ; HL contains value of (Score) LD DE, $2FFF ; DE contains a value CALL CP_HL_DE JR Z, Same ; Go to Same if HL and DE were equal. ----------------------------------------------------------------------------CALL UNPACK_HL ----------------------------------------------------------------------------Inputs: HL = value to "unpack" from Returns: A = value "unpacked" from HL HL = modified, to allow "unpacking" of next number UNPACK_HL "unpacks" one digit from HL. Unpacking means taking the number and dividing it by 10, and putting the remainder into A. This function is also used by D_HL_DECI. Example: LD DE, Digits+4 LD B, 5 ConvertLoop: CALL UNPACK_HL ADD A, '0' LD (DE), A DEC DE DJNZ ConvertLoop ; Location to store the string of 5 characters ; A word can be described by 5 digits. ; ; ; ; ; Unpack a number Now A is the CHARACTER for this value Put that character into the string Point DE to the previous byte in the string Convert all the 5 characters

----------------------------------------------------------------------------CALL STORE_KEY ----------------------------------------------------------------------------Inputs: A = scancode Returns: ($8000) = scancode ($8006) = scancode (if scancode <> 0) SET 3, (IY+$00) STORE_KEY stores a keystroke into the key buffer. This keystroke can then be read by the GET_KEY function. Example: LD A, $09 CALL STORE_KEY ; $09 is scancode for ENTER ; Store ENTER into the key buffer

----------------------------------------------------------------------------CALL GET_KEY ----------------------------------------------------------------------------Inputs: None Returns: A = scancode of last key pressed HL = $8000 RES 3, (IY+$00) GET_KEY is one of the most used ROM functions. It returns the last key that was pressed. The value returned in A is the scancode of the key. If a key is not pressed, instead of waiting for a key, it returns 0. Example: WaitKey: CALL GET_KEY OR A JR Z, WaitKey

; If A is not 0 (a key is pressed), then continue

----------------------------------------------------------------------------ROM_CALL(CLEARLCD) ----------------------------------------------------------------------------Inputs: None Returns: The LCD is cleared. Text/graphics memory are not modified. Many registers are modified. CLEARLCD clears the LCD screen. Since it does not change the text memory, your variables are left alone. Example: ROM_CALL(CLEARLCD) ; Clear the text and start JR Start ----------------------------------------------------------------------------ROM_CALL(CLEARTEXT) ----------------------------------------------------------------------------Inputs: None Returns: None SET 1, (IY+$0D) = fill text memory (8BDF) with spaces RES 1, (IY+$0D) = clear the LCD without altering the text memory CLEARTEXT clears the text memory. If you want to be sure you just clear the LCD and not the memory, use the CLEARLCD function instead.

Example: ROM_CALL(CLEARTEXT) ; Where did the variables go? RET ; Let's go back to CrASH. ----------------------------------------------------------------------------ROM_CALL(SCROLL_UP) ----------------------------------------------------------------------------Inputs: ($8C8F) = first row to scroll (0-7) ($8C90) = last row to scroll (1-8) Returns: None SCROLL_UP scrolls the screen or part of it one line up, and inserts a blank line at the end of it. SET 1, (IY+$0D) = scroll the text memory RES 1, (IY+$0D) = don't scroll the text memory Example: XOR A ; Set A=0 LD ($8C8F), A ; Starting row is 0 LD A, 5 LD ($8C90), A ; Last row to scroll is 5 ROM_CALL(SCROLL_UP) ----------------------------------------------------------------------------ROM_CALL(D_HL_DECI) ----------------------------------------------------------------------------Inputs: HL = decimal 16-bit number to display (CURSOR_POS) with cursor positions. Returns: (CURSOR_POS) updated with new cursor positions. D_HL_DECI displays HL as a 5-digit, right justified, blank-padded decimal number. Example: LD HL, (Score) ; We want to display the value of Score ROM_CALL(D_HL_DECI) ----------------------------------------------------------------------------ROM_CALL(D_ZT_STR) ----------------------------------------------------------------------------Inputs: HL = pointer to zero-terminated string (CURSOR_POS) with cursor positions. Returns: (CURSOR_POS) updated with new cursor positions. HL points to byte after the string. D_ZT_STR displays a text zero-terminated string on the screen. Example: LD HL, Hello ; ROM_CALL(D_ZT_STR) RET ; Hello: .DB "Hello", 0 ; Offset of the string ; Display the string Return from sub-routine (or to CrASH) String to use with a 0 behind

----------------------------------------------------------------------------ROM_CALL(D_LT_STR) ----------------------------------------------------------------------------Inputs: HL = pointer to length indexed string

(CURSOR_POS) with cursor positions. Returns: (CURSOR_POS) updated with new cursor positions. HL points to byte after the string. D_LT_STR displays a normal text string of characters to the screen. The length of the string is determined by the value of the first byte in the string. The cursor coordinades are updated, and HL will point to the next byte after the string. Example: LD HL, Hello ; ROM_CALL(D_LT_STR) RET ; Hello: .DB 5, "Hello" ; Offset of the string ; Display the string Return from sub-routine (or to CrASH) String to use

----------------------------------------------------------------------------ROM_CALL(D_ZM_STR) ----------------------------------------------------------------------------Inputs: HL = pointer to zero-terminated string (GRAF_CURS) with cursor positions Returns: (GRAF_CURS) updated with new cursor positions. HL points to next byte after string. D_ZM_STR displays a zero-terminated string on the screen in mini font. Example: LD HL, Hello ; ROM_CALL(D_ZM_STR) RET ; Hello: .DB "Hello", 0 ; Offset of the string ; Display the string Return from sub-routine (or to CrASH) String to use, with a 0 at the end

----------------------------------------------------------------------------ROM_CALL(D_LM_STR) ----------------------------------------------------------------------------Inputs: HL = pointer to string B = length of string (GRAF_CURS) with cursor positions Returns: (GRAF_CURS) updated with new cursor positions. HL points to next byte after string. D_LM_STR displays a length indexed string on the screen in mini font. Example: LD HL, Hello ; LD B, 5 ; ROM_CALL(D_LT_STR) RET ; Hello: .DB "Hello" ; Offset of the string We want to display 5 characters ; Display the string Return from sub-routine (or to CrASH) String to use

----------------------------------------------------------------------------ROM_CALL(M_CHARPUT) ----------------------------------------------------------------------------Inputs: A = character to display (GRAF_CURS) with cursor positions Returns: (GRAF_CURS) updated with new cursor positions. DE is destroyed.

M_CHARPUT displays the character in A on the screen in mini font. This is the style that is usually used by the TI-82 when in graphics mode. Example: LD HL, $1010 ; HL LD A, 'C' ; We LD (GRAF_CURS), HL ; ROM_CALL(M_CHARPUT) ; contains the coordinates want to display a 'C'. Store the coordinates Display the character

----------------------------------------------------------------------------ROM_CALL(TR_CHARPUT) ----------------------------------------------------------------------------Inputs: A = Character to display Returns: (CURSOR_POS) updated with new cursor positions. TR_CHARPUT displays a raw character to the screen. Example: LD HL, $0207 ; HL contains X and Y position LD (CURSOR_POS), HL ; Store the XY coordinates LD A, 'a' ; Char to put ROM_CALL(TR_CHARPUT) ; Put a at (7,2) ----------------------------------------------------------------------------ROM_CALL(TX_CHARPUT) ----------------------------------------------------------------------------Inputs: A = Character to display (CURSOR_POS) with cursor positions. Returns: (CURSOR_POS) updated with new cursor positions. TX_CHARPUT function displays a single character to the screen. It also converts the character if it is a control character. Example: LD HL, $0000 ; HL contains X and Y position (top left) LD (CURSOR_POS), HL ; Store the XY coordinates LD A, 'A' ; Char to put ROM_CALL(TX_CHARPUT) ; Put A in the top-left corner ----------------------------------------------------------------------------A Guide to the CrASH CALLs ----------------------------------------------------------------------------- EXIT_2_TIOS - CR_KHAND - CR_GRBCopy - CP_HL_BC - RAND ----------------------------------------------------------------------------CALL EXIT_2_TIOS ----------------------------------------------------------------------------Inputs: None Returns: You are back in the normal TI-OS. EXIT_2_TIOS is THE boss key feature of CrASH. You may also use a JP instead of CALL. Example: CALL GET_KEY ; Check for keys pressed

CP G_ZOOM ; Check for the status of ZOOM JP Z, EXIT_2_TIOS ; If ZOOM was pressed, exit to TI-OS. ----------------------------------------------------------------------------CALL CR_KHAND ----------------------------------------------------------------------------Inputs: None Returns: A with keycodes from the standard key handler. CR_KHAND is THE uncrashable key feature of CrASH. Using this function will wipe out TEXT_MEM2, however (the FREE_B memory location). CrASH will automatically reset (IY+$09), allowing the key handler to definitely register a key. Example: CALL CR_KHAND CP K_ENTER JR Z, Option ; Wait for a key to be pressed ; Check if ENTER was pressed. ; If ENTER was pressed, go to option

----------------------------------------------------------------------------CALL CR_GRBCopy ----------------------------------------------------------------------------Inputs: None Returns: Screen updated. CR_GRBCopy is THE fast display feature of CrASH. Using this function will provide a faster display (faster than say, DISP_GRAPH) to the screen allowing for faster game play. None of the registers are modified. CAUTION: If you do change the turbo port of the calculator, remember to set bit 4 of the value. If you do not, it will cause many problems with other programs using the CR_GRBCopy function. The turbo port is reset, however upon returning to CrASH. If you wish to make the calculator have very frequent interrupts (ie max turbo) use $10 for the output value instead of $00. This should resolve problems with CR_GRBCopy. Example: LD HL, GRAPH_MEM LD DE, GRAPH_MEM+1 LD BC, $2FF LD (HL), $FF LDIR CALL CR_GRBCopy ; ; ; ; ; \ | > Fill the GRAPH_MEM with $FF | /

; Display the filled screen

----------------------------------------------------------------------------CALL CP_HL_BC ----------------------------------------------------------------------------Inputs: HL and BC = The words to compare Returns: Updated flags CP_HL_BC compares HL and BC, just as if you had used the CP instruction. Example: LD HL, (Score) ; HL contains value of (Score) LD BC, $2FFF ; BC contains a value CALL CP_HL_BC JR Z, Same ; Go to Same if HL and BC were equal.

----------------------------------------------------------------------------CALL RAND ----------------------------------------------------------------------------Inputs: None Returns: A is a 7-bit pseudorandom number (0-127) CY is also set pseudorandomly RAND yields a random number in A. If you want an 8-bit random number, read the second example. Example: CALL RAND AND %00100000 JR Z, NoBit Example2: CALL RAND RLA ; A contains 0-127 ; Check to see if bit 6 is set ; If bit is not found, go to NoBit ; A contains 0-127 ; CY contains another random bit ; Now it contains 0-255

----------------------------------------------------------------------------Some Notes of Caution ----------------------------------------------------------------------------* CR_GRBCopy and other functions are included for your convenience. Please follow any directions given in the notes above. * Be sure to test that your program runs correctly on all calculators before distributing it. Check for any chances for a crash and please fix them. * Be sure to keep bit 4 of the turbo port of the calculator set if you are using turbo and CR_GRBCopy in your program. CrASH itself resets the turbo port. * When using FREE_B, DO NOT use CR_KHAND unless it is acceptable for CR_KHAND to wipe out any data there. We feel not having another 128 bytes of free memory far outweighs the calculator crashing during KEY_HAND. * Don't use ROM_CALL(KEY_HAND). Make sure you change ALL of these calls to CALL CR_KHAND when porting a program to CrASH. (We do not want crashing programs) * When you use CR_KHAND, the calculator CAN turn off, either by APD or by the user hitting [2nd]+[OFF]. For this reason, PLEASE make sure that your program does not leave the calculator in a state that TI-OS can't handle. * Please notify the authors about any bugs you find while programming for CrASH. * Don't use VAT ROM_CALLs in CrASH because relocation will make the VAT's pointer wrong. We have an idea to fix this, but this will not be done until version 2.0 * When using the APD_BUF memory area (FREE_C), be sure to check INT_STATE and APD_FREE. INT_STATE (byte) will contain 0 if APD_BUF has no interrupts running. APD_FREE (word) will contain the amount of free APD_BUF at the beginning of APD_BUF if any interrupts are being used. THIS MAY BE ZERO. Example:

LD A, (INT_STATE) OR A \ JR Z, Ok LD HL, (APD_FREE) LD DE, $100 CALL CP_HL_DE JR NC, Ok

; Find the Interrupt State ; If clear, then go ahead and use the APD_BUF ; Find the amount of free APD_BUF ; Compare to amount of memory needed (here, $100 bytes) ; Go ahead and use the APD_BUF if enough.

LD HL, $0002 ; Display starting second row LD (CURSOR_POS), HL LD HL, UnloadStr ; Display the UnloadStr ROM_CALL(D_ZT_STR) CALL CR_KHAND RET Ok: . . Program . UnloadStr ; Wait for a key ; Quit

.DB "Please disable " .DB "the interrupt " .DB "that is running.", 0

----------------------------------------------------------------------------Installing an Interrupt Handler ----------------------------------------------------------------------------The following instructions will help you in writing your own interrupt handler to run under CrASH. Note that these things are ONLY necessary if you intend to use APD_BUF to store your interrupt handler AND you want your program to work even outside of your own program, including outside CrASH totally. APD_BUF is the only location you can use acceptably for an interrupt handler because of relocation. Once your program exits, it will no longer be in the same place, and *boom*. Using APD_BUF has strings attached, because other programs may feel like using APD_BUF. For this reason, CrASH programs MUST read the APD in use flag before touching APD memory. Use this to your advantage when writing interrupt handlers. To get CrASH programs to work correctly, you need to do the following: - Copy your code to APD_BUF. It simply will not work any other way, no matter how hard you try. - Check the INT_STATE variable in CrASH RAM (it's part of CrASH). If this is not 0, then you can't install another interrupt because one is in use already in APD_BUF. If your "ID" byte is in INT_STATE, your interrupt is already loaded, though you may want to confirm another way. INT_STATE is an 8 bit variable. - Write your ID value to INT_STATE. Contact us to receive an official ID number that does not conflict with any other. Programs will now know that an interrupt is in use. - Copy your interrupt handler and table AS HIGH IN APD_BUF AS POSSIBLE. The more APD space you use, the less programs will work with your interrupt handler. - Write the number of bytes (16-bits long) still available to programs at APD_FREE. Any memory between and including APD_BUF and APD_BUF+APD_FREE-1 is free game for ANY program. - It's your job to set up the Z80 interrupt stuff. Both the I table and your

handler must be in APD_BUF. - Every time your interrupt is called, you must set INT_STATE to your ID byte again. This is because CrASH zeros it on startup. It is not necessary to set APD_FREE again. - Write $74 to $800A. This will prevent APD from occuring, removing the TI-OS threat of overwriting. (except for mem-resets... but THEN again, you're trying to clear mem...) - Restore all registers. This is pretty obvious. The "prime" registers the second set of registers with ' on them - are reserved for interrupt use. Therefore, EXX is the simplest way to do this, though you can use other ways. - Jump to the original interrupt handler at the end of yours. This is $0038. - When you remove your interrupt handler, load $00 into I, and set INT_STATE to $00. Though not required, please set APD_FREE to $300. Try to test as many CrASH and ASH programs as possible when you write your program. Currently registered ID bytes: $80 = Crash to CrASH $81 = Where are my progs ?

Das könnte Ihnen auch gefallen