; ; banner.s ; ; A startup banner window ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:dbox GET sapphire:divide GET sapphire:event GET sapphire:flex GET sapphire:heap GET sapphire:hour GET sapphire:nopoll GET sapphire:res GET sapphire:sapphire GET sapphire:screen GET sapphire:wimp GET sapphire:dbx.dbx GET sapphire:dbx.slider [ :LNOT::DEF: bnr__dynaLink IMPORT |Image$$RW$$Base|,WEAK IMPORT |Image$$RW$$Limit|,WEAK IMPORT |Sapphire$$ClientData$$Base|,WEAK IMPORT |Sapphire$$ClientData$$Limit|,WEAK IMPORT |Sapphire$$ExtTable$$Base|,WEAK IMPORT |Sapphire$$ExtTable$$Limit|,WEAK ] IMPORT |Sapphire$$LibData$$Base|,WEAK IMPORT |Sapphire$$LibData$$Limit|,WEAK ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY [ :LNOT::DEF: bnr__dynaLink ; --- banner --- ; ; On entry: R0 == pointer to definition block, or 0 ; R1 == R12 value to pass to setup routine, if present ; ; On exit: -- ; ; Use: Displays a startup banner and initialises the library and ; client. This call should be used as a replacement for ; sapphire_libInit. ; ; If R0 is 0 on entry, no banner window is used; instead ; an hourglass percentage is displayed to indicate the ; amount of initialisation performed so far. ; ; Alternatively, it should point to a table consisting of ; a flags word and optional arguments specified by the flags ; in order. The options you can specify are a slider and ; percentage count icon (used to display current progress), ; a setup routine, and the leafname of a sprites file to ; attach to the banner window. ; ; The setup routine is passed the banner dialogue handle in ; R0. It should fill in parts of the banner window, such as ; the licencee name and serial number that can't be determined ; until runtime (for safeness), and maybe version information ; too. EXPORT banner banner ROUT STMFD R13!,{R2,R14} ;Save some registers ADR R2,bnr__initList ;Point to the list BL bnr_doBanner ;Do the job LDMFD R13!,{R2,PC}^ ;And return to caller bnr__initList DCD |Image$$RW$$Limit| DCD |Sapphire$$ClientData$$Base| DCD |Sapphire$$ClientData$$Limit| DCD -1 DCD |Sapphire$$ExtTable$$Base| DCD |Sapphire$$ExtTable$$Limit| LTORG ] ; --- bnr_doBanner --- ; ; On entry: R0 == pointer to definition block, or 0 ; R1 == R12 value to pass to setup routine, if present ; R2 == pointer to library initialisation table ; ; On exit: -- ; ; Use: Displays a startup banner and initialises the library and ; client. EXPORT bnr_doBanner bnr_doBanner ROUT STMFD R13!,{R0-R10,R12,R14} ;Save some registers ; --- Initialise required parts of library --- LDR R0,sapph_appName ;Find the application name BL hour_init ;Initialise hourglass BL hour_on ;Turn on the hourglass BL alloc_init ;Initialise heap functions BL wimp_init ;Initialise WindowManager BL screen_init ;Initialise screen info BL res_init ;Find our resources BL nopoll_init ;We need nonpolling dialogues BL dbox_init ;Initialise dialogue boxes BL flex_init ;Initialise nemory manager BL heap_init ;And the heap manager too ; --- Unpack the definition block --- SUB R13,R13,#36 ;Make a bit of workspace MOV R1,#0 ;Clear two words MOV R2,#0 STMFD R13!,{R1,R2} ;Make two flex anchors STR R1,[R13,#40] ;Initial percentage is 0 MOV R10,#0 ;Not created the block yet LDR R9,[R13,#44] ;Load the block pointer CMP R9,#0 ;Is there a block? BEQ %05bnr_doBanner ;No -- don't bother then ; --- Load the template file --- MOV R0,R13 ;Point to this anchor MOV R1,#2048 ;Guess the size of the file BL flex_alloc ;Try to allocate BCS %05bnr_doBanner ;If it failed, ignore window ADRL R0,bnr__tfile ;Point to template file name MOV R1,R11 ;Build name in scratchpad BL res_find ;Try to find the file BCC %05bnr_doBanner ;If it failed, ignore window MOV R1,R0 ;Point to the name SWI XWimp_OpenTemplate ;Try to open the file LDRVC R1,[R13,#0] ;Load the base of this block ADDVC R2,R1,#1024 ;Indirected data in 2nd K ADDVC R3,R1,#2048 ;And stop at the end please MOVVC R4,#-1 ;Pray there's no fonts ADRVCL R5,bnr__template ;Point to the template name LDMVCIA R5,{R6-R8} ;Load 3 words of data ADDVC R14,R13,#8 ;Point to some free space STMVCIA R14,{R6-R8} ;It writes back the name! MOVVC R5,R14 ;So point to a copy MOVVC R6,#0 ;Start from beginning SWIVC XWimp_LoadTemplate ;Try to load the template MOVVS R7,R0 ;If error, remember pointer MOVVC R7,#0 ;Otherwise clear this SWI Wimp_CloseTemplate ;Close the template file MOVS R0,R7 ;Get the error back BNE %05bnr_doBanner ;And go off somewhere else ; --- Now load options from the block --- MOV R1,R9 ;Move this around a bit LDR R0,[R1],#4 ;Load the flags word TST R0,#bFlag_slider ;Does he want a slider? LDRNE R9,[R1],#4 ;Yes -- load the icon number MOVEQ R9,#-1 ;Otherwise remember this TST R0,#bFlag_counter ;Does he have a counter? LDRNE R8,[R1],#4 ;Yes -- load the icon number MOVEQ R8,#-1 ;Otherwise remember this TST R0,#bFlag_setup ;Does he have a setup routine LDRNE R7,[R1],#4 ;Yes -- load the address MOVEQ R7,#0 ;Otherwise remember this TST R0,#bFlag_sprites ;Does he have a sprite file BEQ %03bnr_doBanner ;No -- don't load it then ; --- Load the sprite file --- MOV R0,R1 ;Point to the leafname MOV R1,R11 ;Build name in scratchpad BL res_find ;Try to get a good name BCC %03bnr_doBanner ;If not there, don't worry MOV R1,R0 ;Put name in right register MOV R0,#17 ;Read information on file SWI XOS_File ;Try to get the information BVS %03bnr_doBanner ;Failed -- don't bother then TST R0,#1 ;Is this a file? BEQ %03bnr_doBanner ;No -- ignore it then ADD R0,R13,#4 ;Point to other anchor ADD R1,R4,#8 ;Get the file size BL flex_alloc ;Allocate the memory BCS %03bnr_doBanner ;Failed -- ignore it then MOV R0,#16 ;Load the file MOV R1,R11 ;Point to the filename LDR R2,[R13,#4] ;Load the block address ADD R14,R4,#8 ;Get this block size STR R14,[R2],#4 ;Save it in the block MOV R3,#0 ;Load where I said to load it SWI OS_File ;Load the file then LDMIA R13,{R0,R1} ;Load the two anchors STR R1,[R0,#64] ;Save the sprite pointer ; --- Now create a dialogue box --- 03bnr_doBanner LDR R0,[R13,#0] ;Load the window base address BL dbox_fromDefn ;Try to create a dialogue BVS %05bnr_doBanner ;If we couldn't, don't care MOV R10,R0 ;Get the dialogue handle ; --- If we need to, build a dbx block --- CMP R9,#-1 ;Do we have a slider icon? ADRNE R14,bnr__dbx ;Yes -- point to dbx skeleton ADDNE R1,R13,#8 ;Point to some spare memory LDMNEIA R14!,{R3-R5} ;Load some values out MOVNE R2,R9 ;Get the icon handle STMNEIA R1!,{R2-R5} ;Store them away LDMNEIA R14!,{R2-R5} ;Load some more values STMNEIA R1!,{R2-R5} ;Save them away too ADDNE R1,R13,#8 ;Point to the dbx block BLNE dbx_declare ;And attach the definition ; --- Set up an event handler --- MOV R1,#0 ;I don't have a handler ADD R2,R13,#40 ;Point to spare word MOV R3,#0 ;Don't care about R12 BL dbox_eventHandler ;Set up the event handler ; --- Now set up the dialogue box --- CMP R7,#0 ;Does he have a setup routine LDRNE R12,[R13,#48] ;Load caller's R12 value MOVNE R14,PC ;Set up return address MOVNE PC,R7 ;And call his routine ADD R7,R13,#40 ;Point to count word BL bnr__count ;Update the counter ; --- Display the dialogue box --- ; ; This is a horrible hack, but I don't care. MOV R1,#dbOpen_centre+dbOpen_persist+dbOpen_nonSub BL dbox_open ;Set up the position nicely BL dbox_window ;Get the window handle ORR R0,R0,#1<<31 ;Don't constrain the mouse BL nopoll_open ;Set up a fake redraw request MOV R1,R11 ;Do this in the scratchpad MOV R0,#1 ;Don't care about event mask BL event_poll ;Send that fake event BL nopoll_close ;Shut nopoll up now ; --- Now we need to count the things to initialise --- 05bnr_doBanner ADD R7,R13,#40 ;Point to count word (again) LDR R5,[R13,#52] ;Load the lib init block ADD R5,R5,#4 ;Skip past program end ADR R0,bnr__ownTable ;Point to our own init table LDMIA R0,{R0,R1} ;Load the base and limit SUB R0,R1,R0 ;Find the table size MOV R6,R0,LSR #4 ;Divide by size of entry MOV R2,R5 ;Get a copy of his table 10bnr_doBanner LDMIA R2!,{R0,R1} ;Load the base and limit CMP R0,#-1 ;Is this the end yet? SUBNE R0,R1,R0 ;Find the table size ADDNE R6,R6,R0,LSR #4 ;Add on number in this table BNE %10bnr_doBanner ;And carry on going SUB R2,R2,#4 ;We overshot a bit LDMIA R2,{R3,R4} ;Load extension table values 12bnr_doBanner CMP R3,R4 ;Reached the end yet? BCS %15bnr_doBanner ;Yes -- phew! MOV R14,PC ;Set up return address LDR PC,[R3],#4 ;Call finding routine SUB R0,R1,R0 ;Find the table size ADD R6,R6,R0,LSR #4 ;Add on number in this table B %12bnr_doBanner ;And carry on going ; --- Now actually initialise things --- 15bnr_doBanner MOV R4,#0 ;Nothing initialised yet LDR R2,sapph_workspace ;Load the main workspace base ADR R0,bnr__ownTable ;Point to our own init table LDMIA R0,{R0,R1} ;Load the base and limit BL bnr__init ;Initialise these bits 20bnr_doBanner LDMIA R5!,{R0,R1} ;Load base and limit from tbl CMP R0,#-1 ;Is this the end yet? BLNE bnr__init ;No -- initialise from here BNE %20bnr_doBanner ;And carry on going SUB R5,R5,#4 ;We went a little too far LDMIA R5,{R3,R5} ;Find the extension table 25bnr_doBanner CMP R3,R5 ;Have we finished yet? BCS %30bnr_doBanner ;Yes -- better stop then MOV R14,PC ;Set up return address LDR PC,[R3],#4 ;Call this routine LDR R2,[R11,-R2] ;Load the workspace base BL bnr__init ;Do some initialisation B %25bnr_doBanner ;And keep on going ; --- Ahhh -- finished --- CMP R10,#0 ;Do we have a dialogue box? BEQ %32bnr_doBanner ;No -- don't wait then 30bnr_doBanner SWI OS_ReadMonotonicTime ;What's the time, Mr Computer ADD R1,R0,#50 ;Wait for a second 31bnr_doBanner SWI OS_ReadMonotonicTime ;What's the time, Mr Computer CMP R0,R1 ;Waited long enough? BMI %31bnr_doBanner ;No -- keep waiting then 32bnr_doBanner MOVS R0,R10 ;Get the dialogue handle BLNE dbox_destroy ;Trash it if I created it LDR R14,[R13,#0] ;Load the dialogue anchor CMP R14,#0 ;Did I create it? ADDNE R0,R13,#0 ;Yes -- point to the anchor BLNE flex_free ;And free the block LDR R14,[R13,#4] ;Load the sprite anchor CMP R14,#0 ;Did I create it? ADDNE R0,R13,#4 ;Yes -- point to the anchor BLNE flex_free ;And free the block BL hour_off ;Turn off the hourglass now ADD R13,R13,#44 ;Restore the stack pointer LDMFD R13!,{R0-R10,R12,PC}^ ;And return to caller bnr__template DCB "banner",0 bnr__tfile DCB "Templates",0 bnr__dbx DCD slider DCD dbxFlag_dataR10+slFlag_horizontal DCD 28 DCD 0 DCB 8,1,1,0 DCD 100 DCD -1 bnr__ownTable DCD |Sapphire$$LibData$$Base| DCD |Sapphire$$LibData$$Limit| LTORG ; --- bnr__init --- ; ; On entry: R0 == base of initialisation table ; R1 == limit of initialisation table ; R2 == pointer to workspace base ; R4 == number of units initialised so far ; R6 == number of items to initialise ; R7 == address of count word ; R8 == counter icon number ; R9 == slider icon number ; R10 == banner dialogue handle ; ; On exit: -- ; ; Use: Initialises a load of library units. bnr__init ROUT STMFD R13!,{R0-R3,R5,R14} ;Save some registers MOV R3,R0 ;Look after this pointer LDR R0,sapph_appName ;Find application's name 00bnr__init CMP R3,R1 ;Have we finished yet? LDMCSFD R13!,{R0-R3,R5,PC}^ ;Yes -- then return LDR R5,[R3,#12] ;Load the init routine addr ADD R3,R3,#16 ;Move the pointer on a bit CMP R5,#0 ;Is there an init routine? MOVNE R14,PC ;Yes -- set up return address MOVNE PC,R5 ;And call the routine STMFD R13!,{R0,R1} ;Save some registers ADD R4,R4,#100 ;Initialised another one MOV R0,R4 ;Get the value in R0 MOV R1,R6 ;How many there actually are BL div_round ;Work out the percentage STR R0,[R7,#0] ;Save the count word away BL bnr__count ;Update the counter LDMFD R13!,{R0,R1} ;And restore the registers B %00bnr__init ;And go round again LTORG ; --- bnr__count --- ; ; On entry: R7 == address of current percentage ; R8 == count icon number ; R9 == slider icon number ; R10 == dialogue box handle ; ; On exit: -- ; ; Use: Displays the count of how much we've done in some cunning ; way. bnr__count ROUT STMFD R13!,{R0-R2,R14} ;Save some registers CMP R10,#0 ;Do we have a dialogue box? BEQ %50bnr__count ;Yes -- handle that then CMP R9,#-1 ;Do we have a slider? MOVNE R0,R10 ;Yes -- get the dialogue MOVNE R1,R9 ;And the icon handle BLNE dbx_update ;And redraw the slider CMP R8,#-1 ;Do we have a count icon? LDRNE R0,[R7,#0] ;Yes -- get the current value MOVNE R1,R11 ;Point to the scratchpad MOVNE R2,#256 ;Give the size of the buffer SWINE OS_ConvertInteger4 ;Convert it to an integer MOVNE R2,R0 ;Point to this text MOVNE R0,R10 ;Get the dialogue handle MOVNE R1,R8 ;And the icon handle BLNE dbox_setField ;And write in the data LDMFD R13!,{R0-R2,PC}^ ;Return to caller 50bnr__count LDR R0,[R7,#0] ;Get the current value SWI Hourglass_Percentage ;Put it in the hourglass LDMFD R13!,{R0-R2,PC}^ ;And return to caller LTORG ; --- Flags --- bFlag_slider EQU (1<<0) ;Has a progress slider ;+0 icon number for slider ;+4 bFlag_counter EQU (1<<1) ;Has a percentage indicator ;+0 icon number for indicator ;+4 bFlag_setup EQU (1<<2) ;Needs a setup routine ;+0 == address of routine ;+4 bFlag_sprites EQU (1<<3) ;Load a sprite file ;+0 == name of sprite file ;+n ;----- That's all, folks ---------------------------------------------------- END