; This is an example file for programming your own interface. This file ; itself is a fully functional interface. If you haven't already, try out ; the IFACE interface on SuperNova. Use [LEFT], [RIGHT], [UP], [DOWN] to ; select a program and [ENTER] to run it. Press the [MORE] button if more ; than 21 programs show up. #include "TI-85.H" .org 0 interfaceaddress: .db "SuperNova IFACE v1.2",0 ; Z-Terminated title of our program ; If you don't want to add a title, simply leave a 0 ; Before we continue with the actual code you need to know about SuperNova's ; internal method for storing the addresses of it's programs. Upon running ; SuperNova, a table at TEXT_MEM is created for this purpose. From ; TEXT_MEM+0 on, there are a series of 2-byte pointers to the start of each ; program found by SN (specified by SEARCH_START and SEARCH_COUNT) ; Thus the nth program in the table can be found by TEXT_MEM+2n ; Example: ; ld hl,TEXT_MEM ; ld e,n <- where n is the program number ; sla n ; ld d,0 ; add hl, de ; HL now points to index for program number n ; ld e,(hl) ; inc hl ; ld d,(hl) ; ex de, hl ; HL now points to the actual program ; Now you can do a ROM_CALL(D_ZT_STR) here to diplay the description. ; One last note, the first program found is program 0, not 1 ; So you just learned that you can't use TEXT_MEM because valuable program ; data is stored there. We have realized that you probably need some memory ; for temporary storage when dealing with menus, lightbars etc... so there ; are 12 bytes of memory that you can use for temporary storage space at ; IFACE_MEM. There is no need to clear this area, SuperNova automatically ; clears this area of memory upon startup. ;****************************************** ; Interface Startup Routine ;****************************************** ; Here's where we load up the interface startup: xor a ld (SEARCH_START),a ; Set the program listing to begin displaying ; programs starting with program 0 ld a,21 ld (SEARCH_COUNT),a ; 3 columns * 7 programs per column ; = 21 programs per page LD_IFACE(initvars,drawroutine,mainroutine) ; Load the Interface! ; initvars is your variable initialization routine ; drawroutine is your routine to display program descriptions ; mainroutine is the core of the interface that handles all input ; and coordinates everything. ret ; Return control back to SuperNova ;****************************************** ; Variable/Register Initialization Routine ;****************************************** ; We must set any variables here and not inside the main routine ; if we don't, the variables will be destroyed probably causing ; the calculator to crash. initvars: ld hl,$0501 ; YOU NEED TO SET THE VALUE FOR THE CURSOR ld (CURSOR_X),hl ; Otherwise nothing at all will show up ld c,0 ; C = Program currently highlighted ret ; Return control to SuperNova so that ; the interface can now be run. ;****************************************** ; Interface Drawing Routine ;****************************************** ; This routine is called by SuperNova when REFRESH is called to display ; program descriptions. Because it is called remember to preserve ALL ; variables or registers with the exception of AF! drawroutine: ld a,(CURSOR_Y) add a,6 ld (CURSOR_Y),a ; Set the lightbar down 6 pixels cp 53 ; Check if we're at the bottom of the screen jr nz,notnextcolumn ld a,11 ; If we're at the bottom, we'll move the ld (CURSOR_Y),a ; cursor back to the top and shift it right ld a,(CURSOR_X) ; one column add a,43 ld (CURSOR_X),a notnextcolumn: ld a,(CURSOR_X) ; Save the cursor column position push hl ; Must PRESERVE HL! ld hl,VAT_NAME ; Load the name of the last valid string that ROM_CALL(D_ZM_STR) ; SuperNova has found and display it! pop hl ; Restore HL ld (CURSOR_X), a ; Restore the cursor column position ret ; Return control to SuperNova ;****************************************** ; Main Interface Engine/Kernel ;****************************************** ; Remember that PROGRAM_ADDR is NOT set correctly yet, but we're going to ; need it to be set correctly, so we use the CALL CURR_ADDR command to do ; this mainroutine: push bc ; Need to save BC because we use registers ; set in the Initialization Routine ld bc,point ; BC = point CALL CURR_ADDR ; HL = (PROGRAM_ADDR) + point point: sbc hl,bc ; HL = HL - BC ; = (PROGRAM_ADDR) + point - point ; = (PROGRAM_ADDR) ld (PROGRAM_ADDR),hl ; (PROGRAM_ADDR) is now correctly set ld a,(PROG_NUM) ; Check how many programs SuperNova found ld c,a cp 0 ; If there were 0, go to NO PROGRAMS handler pop bc jr nz,menustart ; If there are programs, go to the menu keys noprograms: ld hl, $1E29 ld ($8333), hl ; Set the cursor ld de, noprogs ld hl, (PROGRAM_ADDR) add hl, de ROM_CALL(D_ZM_STR) ; Display the message "NO PROGRAMS" getK2: call GET_KEY2 ; Wait for a key cp $37 ret z jr getK2 menustart: push bc ; Still need to preserve BC ld c,63-55 CALL_(drawhorizline) ; Draw horizontal line #1 ld c,63-9 CALL_(drawhorizline) ; Draw horizontal line #2 ld b,42 CALL_(drawvertline) ; Draw vertical line #1 ld b,85 CALL_(drawvertline) ; Draw vertical line #2 pop bc ; Restore BC main: CALL_(drawbar) ; Draws the lightbar CALL_(drawdescript) ; Displays the description at the botton getch: call GET_KEY ; Get the key cp 0 jr z, getch cp $37 ; Exits ret z cp $38 ; More jr z, more CALL_(drawbar) ; Otherwise, reverse (erase) the bar cp 2 CALL_Z(goleft) ; Move Cursor Left cp 3 CALL_Z(goright) ; Move Cursor Right cp 1 CALL_Z(godown) ; Move Cursor Down cp 4 CALL_Z(goup) ; Move Cursor Up cp 9 jr z,run_the_program ; Execute the program jr main ; Not any of those, loop back run_the_program: push bc ; Need to save BC ld hl, (PROGRAM_ADDR) ; Save the program address push hl ; Save the (PROGRAM_ADDR) to hl ld d,0 ; DE = C*2 ld a,c sla a ld e,a CALL RUN_IT ; Execute the program pop hl ld (PROGRAM_ADDR), hl ; Restore (PROGRAM_ADDR) from hl pop bc ; Restore BC ; Restart IFACE but highlight program C ld hl,$0501 ; YOU NEED TO SET THE VALUE FOR THE CURSOR ld (CURSOR_X),hl ; Otherwise nothing at all will show up call REFRESH menuback: jr menustart more: CALL_(initvars) ; Reinitialize all variables ld a,(PROG_NUM) ; How many programs do we have? sra a cp 21 ; If the page is filled, then display the jr nc,reload_the_screen ; next 21 valid programs jr more2 ; Otherwise display the first page again reload_the_screen: ld a,(SEARCH_START) add a, 21 ; Set SEARCH_START to display next 21 ld (SEARCH_START), a ; programs call REFRESH ; Refresh the screen ld a,(PROG_NUM) ; If no programs exist cp 0 ; Display the first page of programs jr nz,menuback ; Otherwise return to menu selection area more2: xor a ; Display first page of programs when ld (SEARCH_START),a ; no more programs are found call REFRESH ; or if the first page isn't full jr menuback ; return to the menu selection area drawdescript: push bc ; Need to save register C ld hl, $3801 ; Set the cursor location to display ld (CURSOR_X), hl ; the description ld hl, TEXT_MEM ; HL = TEXT_MEM ld d,0 ; DE = C * 2 ld a,c ; = Program Index sla a ld e,a add hl, de ; HL = HL + DE = TEXT_MEM + Program Index ld c, (hl) inc hl ld b, (hl) ; Load the pointer to the program to BC push bc pop hl ; HL = BC ROM_CALL(D_ZM_STR) ; Display it dloop2: ; Clear the rest of display ld a, ' ' ROM_CALL(M_CHARPUT) ld a, (CURSOR_X) cp 128 ; If we're at the end of the line jr c, dloop2 ; then quit erasing pop bc ; Restore BC ret ; go back to menu selector ; Keep in mind there are 7 programs listed per column goright: ld b,7 rLoop: CALL_(godown) ; Run the godown routine 7 times djnz rLoop ret ; Return to menu selector goleft: ld b,7 lLoop: CALL_(goup) ; Run the goup routine 7 times djnz lLoop ret ; Return to menu selector godown: push af ; Save AF since we're being CALLed push bc ; Save BC ld b,c ; B = C C = Current Highlighted program inc b ; Add 1 since C starts at 0 ld a,(PROG_NUM) ; Divide by 2 to get total number of sra a ; programs on the screen cp b ; If we're highlighting the last program pop bc ; Restore BC jr z,Edown ; Return to menu selector inc c ; Otherwise highlight the next program Edown: pop af ; Restore AF ret ; Return to menu selector goup: push af ; Save AF since we're being CALLed push bc ; Save BC ld a,c ; If we're highlighting the first program cp 0 ; then we should return back to the selector pop bc ; Restore BC jr z,Eup dec c ; Otherwise highlight previous program Eup: pop af ; Restore AF ret ; Return to menu selector drawhorizline: ; Horizontal line routine ; Cut it if you want and put it in a library ; c = row ld b,0 ROM_CALL(FIND_PIXEL) ld bc, 15 ld de, VIDEO_MEM add hl, de push hl pop de inc de ld (hl), $FF ldir ret drawvertline: ; Vertical line routine ; Cut it if you want and put it in a library ; b = column ld c, 63-56+2 ROM_CALL(FIND_PIXEL) ld de, VIDEO_MEM add hl, de ld b, 48-2 ld de, -16 ld c, a vlineloop: ld a, c or (hl) ld (hl), a add hl, de djnz vlineloop ret drawbar: push bc ; Save Registers push af ; Reverses a 40x6 pixel area as a ; lightbar. Note that running it ; twice will undue itself. ld a,c ld d,0 LdTest: cp 14 ; Determine what column to draw jr c,PassNext ; the lightbar ld d,86 ; D = X pixel position ld a,c ; C = Program number currently sub 14 ; highlighted ld c,a ; Is it column 3? jr NextPart PassNext: cp 7 ; Or is it column 2? jr c,NextPart ; If it's none of these, then ld d,43 ; it must be column 1 ld a,c sub 7 ld c,a NextPart: ld b,a ; Find the Y position of the LdTest2: ; lightbar add a,5 djnz LdTest2 PassLdTest2: add a,11 ; Finally offset Y 11 down neg ; Negate and add 63 because add a,63 ; ROM_CALL(FIND_PIXEL) reads upwards ld c,a ; C = Y ld b,d ; B = X dec b ; Decrement B and Increment C inc c ; to adjust them for the routines ; below ld h,7 ; Draw 7 rows of pixels Light1: dec c ld l,42 ; Draw 42 pixels per row Light2: inc b push hl ROM_CALL(FIND_PIXEL) ld de,VIDEO_MEM add hl,de xor (hl) ld (hl),a ; Reverse the pixel pop hl dec l ld a,l cp 0 jr nz,Light2 ; Check if we're done with the row ld a,b sub 42 ; Reset X for next row ld b,a dec h ld a,h cp 0 jr nz,Light1 ; Check if we're done with columns pop af ; Restore Registers pop bc ret ; Return to menu selector noprogs: .db "NO PROGRAMS!",0 ; Message displayed for NO PROGRAMS .end