|
Tracking Money - Spend Watch exampleDavid Andrews [david@polarnet.com] gets the credit for the inspration on this example. Of course it turned out to be a bit harder than I expected to write it - mostly due to the fact that I wanted it to be a full blown wristapp with lots of features yet still fit on the watch. This one also takes advantage of the 'parent' app which allows setting information in the applet without recompiling it. What was the hardest about this application is making the user interface work and still be intuitive. Once I got past that, coding was just an excercise left to the reader. There are a lot of tricks in this code to make it fit. I created a lot of subroutines and learned some interesting tricks to reduce code size. It currently sits at 713 bytes and I know how I can get 2 more bytes out of it, but I can't find much more fluff in the code to cut out. If you can find ways to make it smaller, I would be more than happy to hear about them... You can download the wristapp and set program here ;Name: spend watch ;Version: spend0 ;Description: spend watch - by John A. Toebes, VIII ;This keeps track of how much is in one of 7 categories ; ; Press the NEXT/PREV buttons to advance/backup through the categories ; Press the SET button to add/subtract/set/clear the amounts in the categories ; If you press the set button while the action is blinking, it will be carried out, otherwise ; you can cancel the operation. ; ;TIP: Download your watch faster: Download a WristApp once, then do not send it again. It stays in the watch! ;HelpFile: watchapp.hlp ;HelpTopic: 106 ;Parent: SpendSet ;**************************************************************************************** ;* Copyright (C) 1997 John A. Toebes, VIII * ;* All Rights Reserved * ;* This program may not be distributed in any form without the permission of the author * ;* jtoebes@geocities.com * ;**************************************************************************************** ; ; History: ; 31 July 96 - Corrected problem with totals not being recalculated when you reenter ; the wristapp. ; INCLUDE "WRISTAPP.I" ; ; (1) Program specific constants ; ; We use a few extra bytes here in low memory. Since we can't possibly ; be running while the COMM app is running, we have no chance of ; conflicting with it's use of this memory. ; BLINK_BUF EQU $5C ; 3 Byte Buffer for the blink routine ; EQU $5D ; EQU $5E CAT_SAVE EQU $5F ; Temporary counter variable COUNTER EQU $60 ; Temporary variable to hold the FLAGBYTE EQU $61 ; Bit 0 indicates that the display does not need to be cleared ; The other bits are not used CURRENT_MODE EQU $62 ; The current mode that we are in MODE_SELECT EQU 0 ; Set mode, selecting which category to modify MODE_HUNDREDS EQU 1 ; Set mode, changing the hundreds of dollars digits MODE_DOLLARS EQU 2 ; Set mode, changing the dollars digits MODE_CENTS EQU 3 ; Set mode, changing the cents MODE_ACTION EQU 4 ; Set mode, changing the action MODE_VIEW EQU 5 ; Normal display mode CATEGORY EQU $63 ; Current category ; ; These three bytes need to be contiguous. The represent the current ; value that is being operated on ; HUNDREDS EQU $64 DOLLARS EQU $65 CENTS EQU $66 ACTION EQU $67 ; Selector for the current action ACT_ADD EQU 0 ACT_SUB EQU 1 ACT_SET EQU 2 ACT_CLEAR EQU 3 AMT_BASE EQU $F0 ; ; ; (2) System entry point vectors ; START EQU * L0110: jmp MAIN ; The main entry point - WRIST_MAIN L0113: rts ; Called when we are suspended for any reason - WRIST_SUSPEND nop nop L0116: jmp DO_UPD ; Called to handle any timers or time events - WRIST_DOTIC L0119: rts ; Called when the COMM app starts and we have timers pending - WRIST_INCOMM nop nop L011c: rts ; Called when the COMM app loads new data - WRIST_NEWDATA nop nop L011f: lda STATETAB0,X ; The state table get routine - WRIST_GETSTATE rts L0123: jmp HANDLE_STATE db STATETAB0-STATETAB0 L0127: jmp HANDLE_STATE db STATETAB1-STATETAB0 ; ; (3) Program strings ; ; These strings represent the 4 possible actions. They need to be early on in the data segment so that ; then can be pointed to by using 8-bit offset addressing. They are exactly 3 bytes long and are ; displayed by using the BLINK_TZONE routine ; S3_MODE: S3_ADD timex "ADD" S3_SUB timex "SUB" S3_SET timex "SET" S3_CLR timex "CLR" ; ; These are the categories that the end user has configured. They are set by using the SPENDSET program ; which searches for the first string "TOTAL ". These strings must be exactly 8 bytes each in order with ; total being the first one. ; S8_TOTAL: timex "TOTAL " S8_CAT1: timex "CAT1 " S8_CAT2: timex "CAT2 " S8_CAT3: timex "CAT3 " S8_CAT4: timex "CAT4 " S8_CAT5: timex "CAT5 " S8_CAT6: timex "CAT6 " S8_CAT7: timex "CAT7 " ; ; These are the running amounts for each category. Note that you can actually ; initialize them with some default and the code will run properly ; AMT_TOTAL: db 0,0,0 AMT_CAT1: db 0,0,0 AMT_CAT2: db 0,0,0 AMT_CAT3: db 0,0,0 AMT_CAT4: db 0,0,0 AMT_CAT5: db 0,0,0 AMT_CAT6: db 0,0,0 AMT_CAT7: db 0,0,0 ; ; These strings prompt for the current mode that we are in. They are displayed on the top line of ; the display. ; S6_SELECT timex6 "SELECT" S6_AMOUNT timex6 "AMOUNT" S6_ACTION timex6 "ACTION" S6_SPEND: timex6 "SPEND" ; save a byte by leaching off the space on the start of the next string S6_WATCH: timex6 " WATCH" ; ; This table selects which string is to be displayed. It is directly indexed by the current mode ; MSG_TAB db S6_SELECT-START ; 0 - MODE_SELECT db S6_AMOUNT-START ; 1 - MODE_HUNDREDS db S6_AMOUNT-START ; 2 - MODE_DOLLARS db S6_AMOUNT-START ; 3 - MODE_CENTS db S6_ACTION-START ; 4 - MODE_ACTION db S6_SPEND-START ; 5 - MODE_VIEW ; ; This is one of the magic tricks for providing the source for the blink routine. ; These are base pointers (offset from HUNDREDS) that we use to copy three bytes into ; BLINK_BUF. The interesting one here is the MODE_CENTS entry which points to DATDIGIT1 ; This works because the last number that we format happens to be the cents amount, ; and the blink routine expects the two characters instead of the actual value. ; DATASRC db HUNDREDS-HUNDREDS ; 1 - MODE_HUNDREDS db DOLLARS-HUNDREDS ; 2 - MODE_DOLLARS db DATDIGIT1-HUNDREDS ; 3 - MODE_CENTS db S3_ADD-HUNDREDS ; 4 - MODE_ACTION 0 - ACT_ADD db S3_SUB-HUNDREDS ; 4 - MODE_ACTION 1 - ACT_SUB db S3_SET-HUNDREDS ; 4 - MODE_ACTION 2 - ACT_SET db S3_CLR-HUNDREDS ; 4 - MODE_ACTION 3 - ACT_CLR ; ; This is the parameter to select which blink routine we want to use ; BLINK_PARM db BLINK_MID12 ; 1 - MODE_HUNDREDS db BLINK_MID34 ; 2 - MODE_DOLLARS db BLINK_SECONDS ; 3 - MODE_CENTS db BLINK_TZONE ; 4 - MODE_ACTION ; ; (4) State Tables ; ; This set of state tables is a little special since we actually use the ; same state processing routine for both states. This saves us a lot of ; memory but still allows us to let the state table make it easy to exit ; the app with the MODE button ; STATETAB0: db 0 db EVT_ENTER,TIM2_12TIC,0 ; Initial state db EVT_RESUME,TIM_ONCE,0 ; Resume from a nested app db EVT_TIMER2,TIM_ONCE,0 ; This is the timer db EVT_MODE,TIM_ONCE,$FF ; Mode button db EVT_SET,TIM_ONCE,1 ; Set button db EVT_DNANY4,TIM_ONCE,0 ; NEXT, PREV, SET, MODE button pressed db EVT_END STATETAB1: db 1 db EVT_RESUME,TIM_ONCE,1 ; Resume from a nested app db EVT_DNANY4,TIM_ONCE,1 ; NEXT, PREV, SET, MODE button pressed db EVT_UPANY4,TIM_ONCE,1 ; NEXT, PREV, SET, MODE button released db EVT_USER2,TIM_ONCE,0 ; Return to state 0 db EVT_END ; End of table ; ; (5) Put up the initial banner screen ; HANDLE_ENTER clra sta CATEGORY ; We start out displaying the totals jsr FETCH_CATEGORY jsr CLEARALL ; Clear the display lda #S6_SPEND-START ; Put 'SPEND ' on the top line jsr PUT6TOP lda #S6_WATCH-START ; Put ' WATCH' on the second line jsr PUT6MID clr FLAGBYTE ; Force us to clear the display lda #MODE_VIEW ; Start out in the VIEW mode sta CURRENT_MODE lda #SYS8_MODE ; Put MODE on the bottom line jmp PUTMSGBOT ; ; (6) This is the main screen update routine. ;--------------------------------------------------------------- ; Routine: ; SHOWCURRENT ; Parameters: ; HUNDREDS,DOLLARS,CENTS - Current value to be displayed ; 0,FLAGBYTE - Screen state (CLR=Must clear it first) ; CATEGORY - the current category to be displayed ; Returns: ; DATDIGIT1,DATDIGIT2 - 2 digit characters for the cents value ; Purpose: ; This routine shows the current selected category and value for the category ;--------------------------------------------------------------- SHOWCURRENT brset 0,FLAGBYTE,NOCLEAR ; If we don't need to clear the display, skip it jsr CLEARALL ; Clear the display bset 0,FLAGBYTE ; And remember that we did it NOCLEAR lda #ROW_MP45 ; Turn on the decimal point sta DISP_ROW bset COL_MP45,DISP_COL ldx HUNDREDS ; Get the Hundreds jsr FMTBLANK0 ; Format it jsr PUTMID12 ; and display it ; ; We want to output the dollars, but if there were no hundreds, we want to let the ; first digit be a blank. To do this, we simply let it be a blank and set it to a zero ; if there was actually anything in the hundreds field ; ldx DOLLARS ; Get the Dollars jsr FMTX ; Format it tst HUNDREDS ; Do we need to have a leading zero? beq NOBLANKIT ; No, so it is fine ldx DOLLARS ; Yes, Get the Dollars again jsr FMTXLEAD0 ; And format it with a leading zero NOBLANKIT jsr PUTMID34 ; Display the Dollars ldx CENTS ; Get the Cents jsr FMTXLEAD0 ; Format it (and leave it around for later) jsr PUTMID56 ; and display it. lda CATEGORY ; Get which category we want lsla ; *2 lsla ; *4 lsla ; *8 add #S8_TOTAL-START ; *8+the start of the string jmp BANNER8 ; and display the right string ; ; (7) State Table 0 and 1 Handler ; This is called to process the state events. ; We see SET, RESUME, DNANY4, and UPANY4 events ; HANDLE_STATE: bset 1,APP_FLAGS ; Indicate that we can be suspended lda BTNSTATE ; Get the event cmp #EVT_ENTER ; Is this the initial state? beq HANDLE_ENTER cmp #EVT_DNANY4 ; How about a button pressed? beq HANDLE_DNANY bclr 1,BTNFLAGS ; Turn off the repeat counter cmp #EVT_SET ; Did they press the set button bne SKIP2 ; No clr CURRENT_MODE ; Yes, Go to MODE_SELECT SKIP2 bra GOREFRESH ; ; (8) They pressed a button, so handle it ; HANDLE_DNANY lda BTN_PRESSED ; Let's see what the button they pressed was beq DO_NEXT ; MODE=1, and NEXT=0, so if it is less, it must be the next button cmp #EVT_SET ; MODE=1 SET=2 PREV=3, test all at once blo DO_MODE ; <2 = 1 so we have a EVT_MODE bhi DO_PREV ; >2 = 3 so we have a EVT_PREV ; ; They pressed the set button, so we want to carry out the operation IF they have ; one currently selected. ; DO_SETOUT lda CURRENT_MODE ; See what mode we were in cmp #MODE_ACTION ; Is it the ACTION mode? bne NO_ACTION ; No, so just cancel the operation jsr DO_OPERATION ; Do what they requested jsr DO_TOTAL ; And total up everything jsr PLAYCONF ; Plus tell them that we did it NO_ACTION bclr 0,FLAGBYTE ; We need to clear the display lda #MODE_VIEW ; And switch back to VIEW mode sta CURRENT_MODE lda #EVT_USER2 ; And go back to state 0 jmp POSTEVENT ; ; (9) This handles the update routine to change a digit... ; DO_NEXT bset 0,SYSFLAGS ; Mark our update direction as up BRSKIP2 ; and skip over the next instruction DO_PREV bclr 0,SYSFLAGS ; Mark our update direction as down DO_UPD lda CURRENT_MODE ; Which mode are we in? beq CHANGE_CATEGORY ; 0=MODE_SELECT, so change the category cmp #MODE_VIEW ; 5=MODE_VIEW, so we also change the category bne TRYOTHERS CHANGE_CATEGORY ; (10) updating the category ldx #CATEGORY ; Point to the category variable lda #7 ; get our range of values bsr ADJUST_PX_ANDA ; And let the routine do the adjust for us jsr FETCH_CATEGORY ; Update the current amount from the new category GOREFRESH bra REFRESH ; ; (11) ADJUST_PX_ANDA - a routine to adjust a value based on the direction ;--------------------------------------------------------------- ; Routine: ; ADJUST_PX_ANDA ; Parameters: ; A - Binary range to limit value within ((2**x)-1) ; 0,SYSFLAGS - Direction to adjust, SET=UP ; X - Pointer to value to be adjusted ; Returns: ; Value pointed to by X is adjusted ; Purpose: ; This routine adjusts a value up or down based on the current direction, wrapping ; it to the binary range indicated by the value in A. Note that this value must ; be a power of 2-1 (e.g. 1, 3, 7, 15, 31, 63, or 127) ;--------------------------------------------------------------- ADJUST_PX_ANDA inc ,X brset 0,SYSFLAGS,NODEC dec ,X dec ,X NODEC and ,X sta ,X rts ; ; (12) Try updating one of the other modes ; We have already handled MODE_SELECT and MODE_VIEW. This code handles ; MODE_HUNDREDS, MODE_DOLLARS, MODE_CENTS, and MODE_ACTION ; TRYOTHERS cmp #MODE_CENTS ; 3=MODE_CENTS bls TRYMORE ; If it is <=, then we leave only MODE_ACTION ; (13) updating the Action lda CATEGORY ; Which category is it? beq REFRESH ; If we are displaying the total, you can't change the action ldx #ACTION ; Point to the current action lda #3 ; and the range of actions bsr ADJUST_PX_ANDA ; and let our simple routine handle it for us bra REFRESH TRYMORE beq DOCENTS ; If it is MODE_CENTS, go handle it ; (14) Update MODE_HUNDREDS=1 and MODE_DOLLARS=2 clrx ; Set the lower limit =0 stx UPDATE_MIN ldx #99 ; And the upper limit= 99 stx UPDATE_MAX add #HUNDREDS-1 ; Point to the right byte to update tax ; And put it in X as the parameter lda CURRENT_MODE ; MODE=1 MODE=2 deca ; 0 1 lsla ; 0 2 add #UPD_MID12 ; 5=UPD_MID12 7=UPD_MID34 jsr START_UPDATEP ; And prepare the update routine bset 4,BTNFLAGS ; Mark that the update is now pending rts ; ; (15) This is where we switch which digit we are changing... ; DO_MODE lda CURRENT_MODE ; Get the mode ldx #MODE_ACTION ; Limit it to the first 5 modes jsr INCA_WRAPX ; And let the system increment it for us sta CURRENT_MODE ; Save it back ; When we switch to the ACTION mode and we have the Totals category showing, ; we need to limit them to the single action of CLEAR ; cmp #MODE_ACTION ; Did we go to action mode? bne REFRESH ; No, nothing to do clr ACTION ; Reset the action to be add tst CATEGORY ; Are we displaying the totals bne REFRESH ; No, nothing more to do lda #ACT_CLEAR ; Yes, switch them to CLEAR sta ACTION ; ; (16) Refresh the screen and start blinking the current digit... ; REFRESH ; 0 - SELECT <Category> ; 1 - AMOUNT (Blink hundreds) ; 2 - AMOUNT (Blink dollars) ; 3 - AMOUNT (Blink cents) ; 4 - ACTION jsr SHOWCURRENT ; Format the screen ldx CURRENT_MODE ; Get the mode lda MSG_TAB,X ; So that we can get the message for it jsr PUT6TOP ; And put that on the top of the display ; ; Now we need to make the right thing blink ; ldx CURRENT_MODE ; Are we in Select mode? beq NOBLINK2 ; Yes, don't blink anything cpx #MODE_ACTION ; How about ACTION MODE? bhi NOBLINK2 ; >ACTION is VIEW mode, so if so, don't blink either ; 1 -> BLINK_MID12 PARM=&HUNDREDS ; 2 -> BLINK_MID34 PARM=&DOLLARS ; 3 -> BLINK_SECONDS PARM=&2Characters ; 4 -> BLINK_TZONE PARM=&3Characters brset 1,BTNFLAGS,NOBLINK2 ; Also, we don't want to be blinking if we are in an update routine bne SETUP_BLINK ; If we were not in action mode, we have the right data source ; Put a > on the display ldx #C_RIGHTARR ; Put a > sign right in front of the action lda #POSL3_5 jsr PUTLINE3 lda CURRENT_MODE ; Get the mode add ACTION ; And add in the action tax ; To compute our data source pointer SETUP_BLINK ; ; (17) Set up the parameters for and call the blink routine ; ldx DATASRC-1,X ; Get the offsetted pointer to the right data lda HUNDREDS,X ; And copy the 3 bytes to our blink buffer sta BLINK_BUF lda HUNDREDS+1,X sta BLINK_BUF+1 lda HUNDREDS+2,X sta BLINK_BUF+2 ldx CURRENT_MODE ; Get our mode again lda BLINK_PARM-1,X ; and use it to pick up which parameter we are passing ldx #BLINK_BUF ; Point to the common blink buffer jsr START_BLINKP ; And do it bset 2,BTNFLAGS ; Mark a blink routine as pending NOBLINK2 rts ; ; (18) Update MODE_CENTS ; This is a special case since we don't have a system routine that allows updating ; the right most digits on the middle line. Fortunately we can fake it by turning ; on the tic timer and waiting until 8 tics have passed before going into a repeat ; loop. The code has been carefully constructed so that the tic timer can just go ; straight to the DO_UPD code to work. DOCENTS ldx #COUNTER ; Point to the counter (saves code size) brset 1,BTNFLAGS,NOSTART ; Are we already in an update loop? lda #8 ; No, we need to wait 8 tics sta ,X ; X->COUNTER ; Save the value BSET 1,BTNFLAGS ; and start the timer bra DOIT ; But still do it once right now ; DEC_DELAY dec ,X ; X->COUNTER ; We haven't hit the limit, decrement it and try again rts NOSTART tst ,X ; X->COUNTER ; We are in the loop, have we hit the limit? bne DEC_DELAY ; no, go off and delay once more DOIT lda #99 ; Our upper limit is 99 ldx #CENTS ; Point to the cents variable (saves code size) brset 0,SYSFLAGS,UPCENTS ; Are we in an up mode? dec ,X ; X->CENTS ; Down, decrement the value bpl REFRESH ; If we didn't wrap, just go display it sta ,X ; X->CENTS ; We wrapped, save the upper limit bra REFRESH ; and go display it UPCENTS inc ,X ; X->CENTS ; Up, increment the value cmp ,X ; X->CENTS ; Did we hit the limit? bpl REFRESH ; No, go display it clr ,X ; X->CENTS ; Yes, wrap to the bottom bra REFRESH ; and display it ; ; (19) DO_OPERATION - Perform the requested operation ;--------------------------------------------------------------- ; Routine: ; DO_OPERATION ; Parameters: ; HUNDREDS,DOLLARS,CENTS - Amount to be added/subtracted/set ; CATEGORY - Item to be updated ; ACTION - 0 = ACT_ADD ; 1 = ACT_SUB ; 2 = ACT_SET ; 3 = ACT_CLEAR ; Purpose: ; Adjusts the corresponding category by the given amount ;--------------------------------------------------------------- DO_OPERATION lda CATEGORY ; Get our category bsr COMPUTE_BASE ; And point to the data for it lda ACTION ; Which action is it? beq DO_ADD ; 0=ADD, go do it cmp #ACT_SET ; 3 way compare here... (code trick) beq DO_SET ; 2=SET, go do it blo DO_SUB ; <2=1 (SUB), go do it DO_CLR ; >2 = 3 (CLEAR) clr HUNDREDS ; Clear out the current values clr DOLLARS clr CENTS tst CATEGORY ; Were we clearing the total? bne DO_SET ; No, just handle it ; ; They want to clear everything ; ldx #(3*8)-1 ; Total number of categories CLEAR_TOTALS ; Mini Routine here X=number of bytes to clear clra CLR_MORE sta AMT_TOTAL,X ; Clear out the next byte decx ; Decrement the number to do bpl CLR_MORE ; And go for more rts ; ; (20) Handle Subtracting a value ; DO_SUB neg HUNDREDS ; Just negate the value to be added neg DOLLARS neg CENTS ; And fall into the add code ; ; (21) Handle Adding a value ; DO_ADD lda CENTS ; Add the cents add AMT_BASE+2,X sta CENTS lda DOLLARS ; Add the dollars add AMT_BASE+1,X sta DOLLARS lda HUNDREDS ; Add the hundreds add AMT_BASE,X sta HUNDREDS ldx #CENTS ; Point to the cents as it will be the first one we fix up tst ACTION ; See what type of operation we just did beq FIXUP_ADD ; Was it an ADD? If so, do do it bsr TRYDEC ; Decrement, fix up the Cents bsr TRYDEC ; Then fix up the dollars lda HUNDREDS ; Did the hundreds underflow as a result? bmi DO_CLR ; Yes, so just set everything to zero bra DO_SET ; No, so copy over the values to the current entry TRYDEC lda ,X ; Get the current byte to check bpl RETDEC ; If it didn't underflow, then skip to the next byte add #100 ; Add back the 100 that it underflowed sta ,X ; And save that away decx ; Back up to the next most significant byte dec ,X ; and borrow the one rts RETDEC decx ; No need to do anything, so skip to the next byte rts TRYADD lda ,X ; Get the current byte to check sub #100 ; See if it was less than 100 bmi RETDEC ; If so, then it was already normalized so skip out sta ,X ; It was an overflow, so save the fixed value decx ; Skip to the next byte inc ,X ; And add in the overflow rts FIXUP_ADD bsr TRYADD ; Fix up the cents bsr TRYADD ; and then fix up the dollars ; ; (22) Handle setting a value ; DO_SET bsr COMPUTE_CATEGORY_BASE ; Point to the data for our category lda HUNDREDS ; Copy over the values to the current category sta AMT_BASE,X lda DOLLARS sta AMT_BASE+1,X lda CENTS sta AMT_BASE+2,X rts ; ; (23) COMPUTE_BASE - Computes an offset pointer to get to the total amounts ; This is a trick to save us a few bytes in the instructions. ;--------------------------------------------------------------- ; Routine: ; COMPUTE_BASE ; Parameters: ; A - Offset into total ; Returns: ; X - Pointer relative to AMT_BASE to use ; Purpose: ; Computes an offset pointer to get to the total amounts ;--------------------------------------------------------------- COMPUTE_CATEGORY_BASE lda CATEGORY ; Get our category COMPUTE_BASE ldx #3 mul add #AMT_TOTAL-AMT_BASE tax rts ; ; (24) This is the main initialization routine which is called when we first get the app into memory ; MAIN: lda #$c0 ; We want button beeps and to indicate that we have been loaded sta WRISTAPP_FLAGS ; Fall into DO_TOTAL ; ; (25) DO_TOTAL - Recomputes the current total ;--------------------------------------------------------------- ; Routine: ; DO_TOTAL ; Parameters: ; NONE ; Purpose: ; Recomputes the current total ;--------------------------------------------------------------- DO_TOTAL lda CATEGORY ; Remember our category sta CAT_SAVE clr ACTION ; Say that we want to add 0=ACT_ADD clr CATEGORY ; To the total category ldx #2 ; But we need to clear it first bsr CLEAR_TOTALS lda #7 ; And iterate over the 7 categories sta COUNTER TOT_LOOP lda COUNTER ; Get our current category bsr FETCH_CATEGORY ; And fetch the data jsr DO_OPERATION ; Then add it to the total dec COUNTER ; Go to the next category bne TOT_LOOP ; Until we are done lda CAT_SAVE ; Restore the category sta CATEGORY ; fall into FETCH_CATEGORY ; (26) FETCH_CATEGORY - Retrieves the value of the total amount for the selected category ;--------------------------------------------------------------- ; Routine: ; FETCH_CATEGORY ; Parameters: ; A - Category to be fetched ; Returns: ; HUNDREDS,DOLLARS,CENTS - Current value of selected category ; Purpose: ; Retrieves the value of the total amount for the selected category ;--------------------------------------------------------------- FETCH_CATEGORY bsr COMPUTE_BASE ; Get the pointer to the base lda AMT_BASE,X ; And retrieve the data sta HUNDREDS lda AMT_BASE+1,X sta DOLLARS lda AMT_BASE+2,X sta CENTS rts ;--------------------END OF CODE--------------------------------------------------- This is a pretty significant program and the sections are ordered to make the branches all work out. Here's a quick lookaround at the sections.
|