; ; sculptrix.s ; ; Draws pretty 3D boxes ; ; © 1994 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sculptrix. ; ; Sculptrix 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. ; ; Sculptrix 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 Sculptrix. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Change history ------------------------------------------------------- ; ; Version By Change ; ~~~~~~~ ~~ ~~~~~~ ; 1.00 MDW Initial version written ; ; 1.01 MDW Added support for group boxes ; Fixed validation string parser -- will now search ; all `X' commands instead of just the first one ; ; 1.02 MDW Fixed problem with multiple unslab ops in one poll ; ; 1.03 MDW Stopped excessive redrawing in group box rendering ; ; 1.04 MDW Done strange things to make text+sprite icons nice ; Any contortions required are due solely to TMA. ; ; 1.05 MDW Filled in group box types 0 and 2 (ridge'n'plinth) ; ; 1.06 MDW Allowed user-changing of the 3D colours and things ; Also included different colours for shaded borders ; ; 1.07 MDW Fixed bug in Sculptrix_SlabIcon, which corrupted R0 ; on exit. Nothing has been affected by this, but we ; may as well get it right. ; ; 1.08 MDW Made colour change before toggling slab on slab ops ; Integrated colour change with toggle slab, now ; box_toggle does all Sculptrix_DoSlab needs to, so ; renamed box_toggle as swi_doslab. Module therefore ; slightly smaller! ; ; 1.09 TMA Added type 7 border -- a writable type with its own ; black border. Less flickery than a Wimp type, ; however, the border is always 4 OS units. ; ; MDW Fixed writable border being black when it gets shaded ; ; 1.10 MDW Made writable border read colours from icon, and fill ; the whole icon with the background colour, rather ; than just the outside. Basically, rewrote the ; border 7 rendering code. ; ; 1.11 MDW Fixed Sculptrix_SetSpriteArea bug -- I `found' my ; workspace twice. Ooops. ; MDW Changed to use new Acorn-allocated SWI chunk number ; ; 1.12 MDW Improved shaded-icon checking to avoid branch. ; Added 10cs delay to unslab with window open in line ; with STASIS requirements. ; ; 1.13 MDW Fixed bug in mitre start position -- inserted RSB ; to make it go in the right direction. ; ; 1.14 MDW Removed filling in groupbox type 0 to allow dbx ; controls to be within group boxes. ; ; 1.15 MDW Modified rendering of `xs' icons to match new STEEL ; and Sapphire icon shading habits. Added a 256-byte ; static buffer for group titles, to avoid dynamic ; allocation in mid-redraw, Changed lots of signed ; compares to unsigned, which removes some redundancy. ; Fixed text+sprite handling to look in Wimp area ; if not in user area. Added messages support. Added ; border type 8 for partitions that fade properly ; (suggested by Alex Thoukydides). ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET sh.messages IMPORT s_help ;----- PLOT code numbers ---------------------------------------------------- plot_MOVE EQU 0 plot_FORE EQU 1 plot_INVERSE EQU 2 plot_BACK EQU 3 plot_RELATIVE EQU 0 plot_ABSOLUTE EQU 4 plot_RECTFILL EQU 96 plot_LINE EQU 0 ;----- VDU variable numbers ------------------------------------------------- vdu_XEIG EQU 4 vdu_YEIG EQU 5 ;----- Module header -------------------------------------------------------- AREA |!!!Module$$Header|,CODE,READONLY DCD 0 ;Module start code DCD s_init ;Initialisation DCD s_die ;Finalisation DCD s_service ;Service call DCD s_title ;Module title string DCD s_help ;Module help string DCD s_command ;Command table DCD &4A2C0 ;SWI chunk (temporary) DCD s_swic ;SWI handling DCD s_swin ;SWI names table DCD 0 ;SWI names code ;----- Module strings ------------------------------------------------------- s_title DCB "Sculptrix",0 ;----- SWI name table ------------------------------------------------------- s_swin DCB "Sculptrix",0 DCB "RedrawWindow",0 DCB "DoSlab",0 DCB "SlabIcon",0 DCB "UnslabIcon",0 DCB "BoundingBox",0 DCB "PlotIcon",0 DCB "PlotGroupBox",0 DCB "SetSpriteArea",0 DCB "UpdateIcon",0 DCB "SlabColour",0 DCB 0 ;----- Command table -------------------------------------------------------- s_command DCB "Sculptrix_Colours",0 DCD cmd_colours DCB 0,0,1,0 DCD synt_colours DCD help_colours DCB "Sculptrix_GroupType",0 DCD cmd_group DCB 1,0,1,0 DCD synt_group DCD help_group DCD 0 ;----- Initialisation and finalisation -------------------------------------- s_init ROUT STMFD R13!,{R14} ;Stack link register nicely ; --- Get some workspace --- MOV R0,#6 ;Allocate workspace MOV R3,#s_wsize ;Make it *this* big SWI XOS_Module ;Get me memory LDMVSFD R13!,{PC} ;Return if it barfed STR R2,[R12] ;Stash the workspace pointer MOV R12,R2 ;Move the pointer across ; --- Set initial values --- BL vdu_set ;Set up the graphics vars MOV R0,#0 ;Initial flags setting STR R0,s_flags ;Store in the flags word MOV R0,#1 ;Start using WIMP area STR R0,s_sarea ;Store in sprite area word MOV R0,#&0400 ;Default colours ORR R0,R0,R0,LSL #16 ;Propagate to top half MOV R1,#&0200 ;Default colours ORR R1,R1,R1,LSL #16 ;Propagate to top half MOV R2,#&0C00 ORR R2,R2,#&000E ADR R3,s_colours STMIA R3,{R0-R2} ; --- I think that's it --- LDMFD R13!,{PC}^ ;Return to caller happy LTORG s_die ROUT STMFD R13!,{R11,R14} MOV R11,R12 ;Keep the private word ptr LDR R12,[R12] ;Find my workspace ; --- Free my workspace --- MOV R0,#7 ;Free RMA space MOV R2,R12 ;Point to workspace SWI XOS_Module ;Try to free the memory MOV R0,#0 ;Gonna zero the private word STR R0,[R11] ;Then zero it LDMFD R13!,{R11,PC}^ ;A happy bunny LTORG ;----- Service call handling ------------------------------------------------ s_service ROUT CMP R1,#&46 ;Is it a mode change? MOVNES PC,R14 ;No -- return LDR R12,[R12] ;Get my workspaxe B vdu_set ;Set up the VDU variables ;----- Command handlers ----------------------------------------------------- ; --- Sculptrix_Colours --- cmd_colours ROUT STMFD R13!,{R1-R5,R14} ;Save some registers LDR R12,[R12] ;Locate my workspace pointer ; --- If no argument, use the default --- CMP R1,#0 ;Is there an argument? ADREQ R0,cmd__defCol ;No -- point to default ; --- Read normal 3D colours --- LDRB R2,[R0],#1 ;Get the first digit BL %50cmd_colours ;Convert to binary MOV R3,R2,LSL #8 ;Look after it LDRB R2,[R0],#1 ;Get the next digit BL %50cmd_colours ;Convert to binary ORR R3,R3,R2 ;Mix into the word nicely ORR R3,R3,R3,LSL #16 ;Propagate to upper half ; --- Read shaded 3D colours --- LDRB R2,[R0],#1 ;Get the first digit BL %50cmd_colours ;Convert to binary MOV R4,R2,LSL #8 ;Look after it LDRB R2,[R0],#1 ;Get the next digit BL %50cmd_colours ;Convert to binary ORR R4,R4,R2 ;Mix into the word nicely ORR R4,R4,R4,LSL #16 ;Propagate to upper half ; --- Read the other colours --- LDRB R2,[R0],#1 ;Get a digit BL %50cmd_colours ;Convert to binary MOV R5,R2,LSL #8 ;Look after it LDRB R2,[R0],#1 ;Get a digit BL %50cmd_colours ;Convert to binary ORR R5,R5,R2 ;Look after it ; --- Now store these away nicely --- ADR R1,s_colours ;Point to base address STMIA R1,{R3-R5} ;Store them in workspace LDMFD R13!,{R1-R5,PC}^ ;Return to caller ; --- Convert R2 to binary --- 50cmd_colours SUBS R2,R2,#'0' ;Convert a digit CMP R2,#10 ;Is this bigger than 9? SUBCS R2,R2,#7 ;Yes -- convert from upper CMP R2,#16 ;Still out of range? SUBCS R2,R2,#&20 ;Yes -- must have been lower CMP R2,#16 ;Still out of range? BCS %51cmd_colours ;Yes -- that's an error MOVS PC,R14 ;Return to caller 51cmd_colours ADRL R0,msg_errBadHex ;Point to error message LDMFD R13!,{R1-R5,R14} ;Unstack the registers ORRS PC,R14,#V_flag ;Return to caller cmd__defCol DCB "4020CE",0 LTORG ; --- Sculptrix_GroupType --- cmd_group ROUT LDRB R0,[R0] ;Get the digit LDR R12,[R12] ;Find my workspace LDR R1,s_flags ;Load my flags word BIC R1,R1,#s_CHANNEL :OR: s_FAINTCHAN CMP R0,#'1' ;Is it a deep channel? ORREQ R1,R1,#s_CHANNEL CMP R0,#'2' ;Is it a shallow channel? ORREQ R1,R1,#s_CHANNEL :OR: s_FAINTCHAN STR R1,s_flags MOVS PC,R14 LTORG ;----- SWI names and numbers etc -------------------------------------------- s_swic ROUT LDR R12,[R12] ;Get my workspace neatly CMP R11,#(%01s_swic-%00s_swic)/4 ;Check SWI is in range ADDCC PC,PC,R11,LSL #2 ;Go to correct branch instr B %01s_swic ;Branch to complain thing 00s_swic B swi_redraw B swi_doslab B swi_slab B swi_unslab B swi_bbox B swi_ploticon B swi_plotgroup B swi_spritearea B swi_update B swi_slabcol 01s_swic ADRL R0,msg_errBadSwi ;Point to error message ORRS PC,R14,#V_flag ;Return with an error LTORG ;----- SWI handling --------------------------------------------------------- ; --- Sculptrix_RedrawWindow --- ; ; R1 == pointer to redraw block swi_redraw ROUT STMFD R13!,{R0-R11,R14} ;Stack registers ; --- Find the window origin --- MOV R11,R1 ;Keep the pointer nicely BL box_readRectangle ;Find everything about rdrw ; --- Now go through the icons --- SUB R13,R13,#40 ;Make way for an icon block MOV R1,R13 ;Point to the block LDR R0,[R11,#0] ;Get the window handle MOV R2,#0 ;Start at icon 0 STMIA R1,{R0,R2} ;Store them in the block ; --- Main loop -- go through each icon and plot --- 00swi_redraw SWI XWimp_GetIconState ;Read info into block ADDVS R13,R13,#44 ;Error -- reclaim stack space LDMVSFD R13!,{R1-R11,PC} ;And return to caller LDR R0,[R1,#24] ;Get the flags word CMP R0,#1<<23 ;Is it only deleted? ADDEQ R13,R13,#40 ;Yes -- reclaim stack space LDMEQFD R13!,{R0-R11,PC}^ ;And return to caller ; --- Find out whether the icon is visible --- ADD R0,R1,#8 ;Point to coords block LDMIA R0,{R0,R2-R4} ;Load the icon coordinates CMP R0,R7 CMPLE R2,R8 CMPLE R5,R3 CMPLE R6,R4 BGT %01swi_redraw ;Not visible -- skip it ADD R0,R1,#8 ;Point to icon block BL box_ploticon ; --- Ho-hum. Now do the next one --- 01swi_redraw LDR R0,[R1,#4] ;Get the icon handle ADD R0,R0,#1 ;Bump it up a little STR R0,[R1,#4] ;Store it back again B %00swi_redraw ;And go round for another LTORG ; --- Sculptrix_DoSlab --- ; ; On entry: R0 == window handle ; R1 == icon number ; R2 == colour to slab to ; ; On exit: R2 == old colour of icon, or -1 if icon couldn't be slabbed swi_doslab ROUT STMFD R13!,{R0-R11,R14} ;Stack registers MOV R9,R2 ;Look after the colour MOV R2,#-1 ;Store -1 in stacked R2 STR R2,[R13,#8] ;Return no colour currently ; --- Find out if we need to do anything --- SUB R13,R13,#44 ;Make way for an icon def STMIA R13,{R0,R1} ;Store icon handle and stuff MOV R1,R13 ;Point to icon block SWI XWimp_GetIconState ;Get the icon information ADDVS R13,R13,#48 ;If it failed, reclaim stack LDMVSFD R13!,{R1-R11,PC} ;And return the error MOV R3,#0 ;Start from the beginning 90swi_doslab ADD R0,R1,#8 ;Point to actual icon def MOV R2,#'X' ;Get the validation command BL box_findValid ;Find the validation string CMP R2,#0 ;Did it work? ADDEQ R13,R13,#44 ;No -- reclaim used stack LDMEQFD R13!,{R0-R11,PC}^ ;And return to caller ; --- Get the border type -- only 0 and 2 slab --- LDRB R0,[R2,#1] ;Get the border type number CMP R0,#'0' ;Is it a normal action type? CMPNE R0,#'2' ;Or a default action type? MOVNE R3,R2 ;No -- point to this place BNE %90swi_doslab ;And loop back ; --- It's a worthwhile icon --- LDMIA R1,{R0,R1} ;Load window and icon handles MOV R8,R2 ;Look after this pointer MOV R2,R9 ;Get the colour wanted BL box_setcolour ;Set the colour properly STR R2,[R13,#44+8] ;Store it nicely away again MOV R1,R13 ;Point at the block again ; --- Update the border --- LDRB R0,[R8,#0] ;Get the border command EOR R0,R0,#&20 ;Toggle its case STRB R0,[R8,#0] ;Store it back again LDR R3,[R1,#24] ;Load the icon flags EOR R3,R3,#&005F0000 ;Toggle ESG and shaded bit TST R3,#1<<22 ;Is the icon shaded? TSTNE R3,#&001F0000 ;No -- test the ESG bits ADRNE R11,s_colours ;No -- use normal colours ADREQ R11,s_shadeCols ;Yes -- use shaded colours TST R0,#&20 ;Is it set now? ADDEQ R11,R11,#1 ;No -- use offset colours ADD R0,R1,#8 ;Point to icon def again LDMIA R0,{R3-R6} ;Get icon coords SUB R3,R3,#4 ;Make space for border around SUB R4,R4,#4 ADD R5,R5,#4 ADD R6,R6,#4 STMIB R1,{R3-R6} ;That's now our update block SWI XWimp_UpdateWindow ;Try and update it then BVS %01swi_doslab ;If it failed skip this bit CMP R0,#0 ;Is there anything to do? BEQ %01swi_doslab ;No -- skip it too ADD R2,R1,#16 ;Point to y1 LDMIA R2,{R8-R10} ;Get coordinates from block SUB R10,R8,R10 ;Get y origin position LDR R8,[R2,#-12] ;Get x0 value from block SUB R9,R8,R9 ;Get x origin position ADD R3,R3,#4 ;Point back to the icon block ADD R3,R3,R9 ADD R4,R4,#4 ADD R4,R4,R10 SUB R5,R5,#4 ADD R5,R5,R9 SUB R6,R6,#4 ADD R6,R6,R10 00swi_doslab ; --- Draw box (inline copy) --- ; ; We only draw the inner slabbed bit -- the rest doesn't ; change even in the default type. ADD R2,R1,#4 STMIA R2,{R3-R6} ;Store adjusted coords away LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R2 BL prim_left LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R2 BL prim_right BL prim_bottom LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R2 BL prim_top ; --- Get another rectangle --- SWI XWimp_GetRectangle CMP R0,#0 ;Have we anything to do? BNE %00swi_doslab ;Yes -- do it then, dummy 01swi_doslab ADD R13,R13,#44 LDMFD R13!,{R0-R11,PC}^ LTORG ; --- Sculptrix_SlabIcon --- ; ; On entry: R0 == window handle ; R1 == icon handle ; R2 == pointer to 4 word slab descriptor to be filled in ; On exit: -- swi_slab ROUT STMFD R13!,{R0-R2,R10,R14} ;Keep link register safe ; --- Fill in the caller's descriptor block --- MOV R10,R2 ;Keep the pointer safe STMIA R10,{R0,R1} ;Stash the icon info away SWI XOS_ReadMonotonicTime ;Read the current time CMP R1,#0 ;Are mouse buttons pressed? ADDEQ R0,R0,#5 ;No -- then bump time on 5 STR R0,[R10,#12] ;Store in the descriptor ; --- Slab the border in or out --- LDR R0,[R10,#0] ;Reload window handle LDRB R2,s_slabcol ;Get the slab colour nicely BL swi_doslab ;Do the slabbing operation LDMVSFD R13!,{R0-R2,R10,PC} ;If it failed, return error SUB R13,R13,#20 ;Space for a pointer block MOV R1,R13 ;Point to the block SWI XWimp_GetPointerInfo ;Read current mouse state LDR R1,[R13,#8] ;Load the button state ADD R13,R13,#20 ;Restore the stack pointer CMP R1,#0 ;Are there buttons pressed? ORREQ R2,R2,#256 ;Yes -- set a flag bit then STR R2,[R10,#8] ;Store the old icon colour ; --- Say to pause on unslabs in flags --- LDR R14,s_flags ;Get the flags word BIC R14,R14,#s_UNSLAB ;Clear unslab bit STR R14,s_flags ;Store flags word back ; --- Return to caller --- LDMFD R13!,{R0-R2,R10,PC}^ ;Return to caller LTORG ; --- Sculptrix_UnslabIcon --- ; ; On entry: R2 == pointer to descriptor filled in by Sculptrix_SlabIcon ; On exit: -- swi_unslab ROUT STMFD R13!,{R0-R2,R10,R14} ;Stack my registers ; --- Find out if we need to do any slabbing --- LDR R14,[R2,#8] ;Get the icon colour CMP R14,#-1 ;Is it nonslabbed? LDMEQFD R13!,{R0-R2,R10,PC}^ ; --- Do we unslab quickly? --- MOV R10,R2 ;Look after slab block SUB R13,R13,#36 ;To read the window state LDR R0,s_flags ;Get the flags word TST R0,#s_UNSLAB ;Is the unslab bit set? BNE %03swi_unslab ;Yes -- skip past the wait ; --- Wait the requisite quantity of time --- LDR R0,[R10,#0] ;Get the window handle MOV R1,R13 ;Point to the block STR R0,[R1,#0] ;Store in the block SWI XWimp_GetWindowState ;Get info about the window BVS %01swi_unslab ;It must have been deleted LDR R0,[R1,#32] ;Get the window flags TST R0,#1<<16 ;Is the window open? BEQ %01swi_unslab ;And just wait the time out ; --- Wait for the mouse to be released --- LDR R14,[R10,#8] ;Load colour and flags bits TST R14,#256 ;Is the `no mouse' bit set? BNE %01swi_unslab ;And do the wait operation 00swi_unslab SWI XOS_Mouse ;Read mouse information CMP R2,#0 ;Are the buttons released? BNE %00swi_unslab ;No -- keep waiting B %03swi_unslab ;Do the actual unslab ; --- Wait for the timer to elapse --- 01swi_unslab LDR R1,[R10,#12] ;Load the slab time ADD R1,R1,#10 ;Work out unslab time 02swi_unslab SWI XOS_ReadMonotonicTime ;Get the current time CMP R1,R0 ;How do they compare? BPL %02swi_unslab ;Too low -- go round again ; --- Actually unslab the icon --- 03swi_unslab ADD R13,R13,#36 ;Reclaim the stack space LDMIA R10,{R0-R2} ;Get window, icon and colour AND R2,R2,#255 ;Clear flags bits etc. BL swi_doslab ;Unslab the icon ; --- Remember we've done this now --- LDR R0,s_flags ;Get the flags word again ORR R0,R0,#s_UNSLAB ;Set the unslab bit STR R0,s_flags ;Store the flags word away ; --- Return to caller --- LDMFD R13!,{R0-R2,R10,PC}^ ;Return to caller LTORG ; --- Sculptrix_BoundingBox --- ; ; On entry: R1 == pointer to an icon block ; On exit: R0 == 0 if there was no border ; block updated to reflect border width swi_bbox ROUT STMFD R13!,{R1-R6,R14} ;Stash registers MOV R3,#0 ;Start from the beginning 00swi_bbox MOV R0,R1 ;Point to block MOV R2,#'X' ;The correct magic command BL box_findValid ;Find the validation string CMP R2,#0 ;Was it not there? MOVEQ R0,#0 ;Mark as nonpresent LDMEQFD R13!,{R1-R6,PC}^ ;Then return LDRB R0,[R2,#1] ;Get the border type CMP R0,#'g' ;It could be a group box CMPNE R0,#'G' ;Try both cases BEQ %02swi_bbox ;If so, be clever SUBS R0,R0,#'0' ;Turn into a number CMP R0,#6 ;Is it type 6? BEQ %01swi_bbox ;Yes -- be clever CMP R0,#9 ;Is it too big? MOVCS R3,R2 ;Not there if too high BCS %00swi_bbox ;So try for another one LDMIA R1,{R3-R6} ;Load the bounding box regs ADR R2,box_borders ;Get the border size table LDRB R0,[R2,R0] ;Load the border width SUB R3,R3,R0 SUB R4,R4,R0 ADD R5,R5,R0 ADD R6,R6,R0 STMIA R1,{R3-R6} ;Store the sizes back LDMFD R13!,{R1-R6,PC}^ ;Return happy 01swi_bbox LDMIA R1,{R3-R6} ;Load the bounding box regs SUB R3,R3,#4 ADD R5,R5,#4 STMIA R1,{R3-R6} MOV R0,#1 LDMFD R13!,{R1-R6,PC}^ ;Return happy 02swi_bbox LDMIA R1,{R3-R6} ;Load the bounding box regs SUB R3,R3,#8 SUB R4,R4,#8 ADD R5,R5,#8 ADD R6,R6,#32 STMIA R1,{R3-R6} MOV R0,#1 LDMFD R13!,{R1-R6,PC}^ ;Return happy box_borders DCB 4,8,12,8,4,4,0,12,4 ROUT ; --- Sculptrix_PlotIcon --- ; ; On entry: R0 == pointer to icon block ; R1 == pointer to redraw block swi_ploticon ROUT STMFD R13!,{R0-R11,R14} ;Stash loads of registers LDMIA R0,{R0,R2-R8} ;Load the icon coordinates STMFD R13!,{R0,R2-R8} ;Store them on the stack BL box_readRectangle ;Get the graphics window size MOV R0,R13 ;Point to the icon block BL box_ploticon ;Plot the icon ADD R13,R13,#32 ;Reclaim the space LDMFD R13!,{R0-R11,PC}^ ;Return to caller LTORG ; --- Sculptrix_PlotGroup --- ; ; On entry: R0 == pointer to icon block ; R1 == pointer to redraw block ; R2 == border type ; R3 == pointer to title string swi_plotgroup ROUT STMFD R13!,{R0-R11,R14} ;Stash loads of registers LDMIA R0,{R0,R4-R10} ;Load the icon coordinates STMFD R13!,{R0,R4-R10} ;Store them on the stack BL box_readRectangle ;Get the graphics window size MOV R0,R13 ;Point to the icon block MOV R1,R2 ;Get border type number MOV R2,R3 ;Get pointer to group string BL box_dogroup ;Plot the icon ADD R13,R13,#32 ;Reclaim the space LDMFD R13!,{R0-R11,PC}^ ;Return to caller LTORG ; --- Sculptrix_SetSpriteArea --- ; ; On entry: R0 == pointer to sprite area to use swi_spritearea ROUT STR R0,s_sarea ;Save it as sprite area ptr MOVS PC,R14 ;Return to caller ; --- Sculptrix_UpdateIcon --- ; ; On entry: R0 == window handle ; R1 == icon handle to update swi_update ROUT STMFD R13!,{R0-R4,R14} ;Save some registers SUB R13,R13,#84 ;For icon and redraw blocks STMIA R13,{R0,R1} ;Save the bits at the bottom MOV R1,R13 ;Point to the icon block SWI XWimp_GetIconState ;Find the icon's bits out BVS %99swi_update ;If it failed, go ahead ADD R2,R13,#40 ;Point to the redraw block LDR R0,[R13,#0] ;Get the window handle again STR R0,[R2,#0] ;Store window handle at base ADD R0,R1,#8 ;Point to icon coordinates LDMIA R0,{R0,R1,R3,R14} ;Load the coordinates SUB R0,R0,#16 ;Include the border nicely SUB R1,R1,#16 ADD R3,R3,#16 ADD R14,R14,#16 STMIB R2,{R0,R1,R3,R14} ;Save them out again MOV R1,R2 ;Point to this block SWI XWimp_UpdateWindow ;Start the window redraw BVS %99swi_update ;If it failed, go ahead 00swi_update CMP R0,#0 ;Is this the end yet? BEQ %80swi_update ;Yes -- finish up nicely ADD R0,R13,#8 ;Point to the icon block BL swi_ploticon ;Plot the icon on the screen SWI XWimp_GetRectangle ;Get the next redraw rect B %00swi_update ;And draw that one too 80swi_update ADD R13,R13,#84 ;Reclaim all that stack LDMFD R13!,{R0-R4,PC}^ ;Return to caller 99swi_update ADD R13,R13,#88 ;Reclaim stack + R0 LDMFD R13!,{R1-R4,PC} ;Return with V still set LTORG ; --- Scultrix_SlabColour --- ; ; On entry: -- ; ; On exit: R2 == standard slabbing-in colour swi_slabcol LDRB R2,s_slabcol MOVS PC,R14 ;----- Icon box redrawing --------------------------------------------------- ; --- box_readRectangle --- ; ; On entry: R1 == pointer to a Wimp redraw block ; On exit: R1 corrupted ; R5-R8 == adjusted, window-relative mouse rectangle ; R9,R10 == screen coords of window origin box_readRectangle ROUT CMP R1,#0 ;Is there a redraw block? MOVEQ R9,#0 ;Yes -- don't translate box MOVEQ R10,#0 MOVEQS PC,R14 ;And return ADD R1,R1,#16 ;Point to y1 LDMIA R1,{R8-R10} ;Get coordinates from block SUB R10,R8,R10 ;Get y origin position LDR R8,[R1,#-12] ;Get x0 value from block SUB R9,R8,R9 ;Get x origin position ; --- Mangle the graphics rectangle --- ADD R1,R1,#12 ;Point to the graphics window LDMIA R1,{R5-R8} ;Load the window posn SUB R5,R5,R9 ;Convert to window coords SUB R6,R6,R10 SUB R7,R7,R9 SUB R8,R8,R10 SUB R5,R5,#16 ;Add a little bit of leeway SUB R6,R6,#32 ADD R7,R7,#16 ADD R8,R8,#16 MOVS PC,R14 LTORG ; --- box_ploticon --- ; ; On entry: R0 == pointer to an icon block (writable) ; R5-R10 == as set by box_readRectangle ; On exit: R2-R4,R11 corrupted box_ploticon ROUT MOV R3,#0 00box_ploticon STMFD R13!,{R14} MOV R2,#'X' ;Find X commands in valid BL box_findValid ;Is it there? LDMFD R13!,{R14} ;Get return address back CMP R2,#0 ;Check MOVEQS PC,R14 ;No -- return to caller ; --- If the border has a capital letter, invert --- ; ; Also, choose the right colours for shaded boxes LDR R11,[R0,#16] ;Get the icon flags word EOR R11,R11,#&005F0000 ;Toggle ESG and shaded bits TST R11,#1<<22 ;Is the icon shaded? TSTNE R11,#&001F0000 ;Or is ESG all set? ADRNE R11,s_colours ;No -- use normal colours ADREQ R11,s_shadeCols ;Yes -- use shaded colours LDRB R4,[R2,#0] ;Get the command letter TST R4,#&20 ;Is it upper case? ADDEQ R11,R11,#1 ;Yes -- use offset colours ; --- Get the render type, and handle as required --- LDRB R3,[R2,#1] ;Get the border type number ORR R4,R3,#&20 ;Convert to lower case CMP R4,#'g' ;Is it a group box type? BEQ box_plotgroup ;Yes -- plot a group box CMP R4,#'s' ;Is it a gadget text/sprite? BEQ box_plottns ;Yes -- plot cunningly ; --- Dispatch normal group border numbers --- SUB R3,R3,#'0' ;Convert to a digit CMP R3,#(%02box_ploticon-%01box_ploticon)/4 ADDCC PC,PC,R3,LSL #2 ;Go to branch table B %03box_ploticon ;Not found -- try next valid 01box_ploticon B brd0 ;Standard plinth B brd1 ;Group ridge/channel B brd2 ;Default action button B brd3 ;Writable wide border B brd0 ;Nonslabbing standard plinth B brd5 ;Plinth with ridge intersect B brd6 ;Channel terminators B brd7 ;Writable with black border B brd8 ;Like 4, only different 02box_ploticon 03box_ploticon MOV R3,R2 ;Point to that command B %00box_ploticon ;And find the next string LTORG ; --- box_setcolour --- ; ; On entry: R0 == window handle ; R1 == icon handle ; R2 == colour to set ; On exit: R2 == old colour of icon box_setcolour ROUT STMFD R13!,{R0,R1,R3-R5,R14} ;Stack registers MOV R5,R2 ;Keep the colour safe SUB R13,R13,#40 ;Make way for icon block STMIA R13,{R0,R1} ;Set up icon block MOV R1,R13 ;Point to block SWI XWimp_GetIconState ;Get info about icon ADDVS R13,R13,#44 ;If it failed, reset stack LDMVSFD R13!,{R1,R3-R5,PC} ;And return the error ; --- Check for fonts --- LDR R0,[R1,#24] ;Get icon flags word TST R0,#1<<6 ;Check anti-aliased bit BEQ %00box_setcolour ;Reset -- do it normally ADD R0,R1,#8 ;Point to icon definition MOV R2,#'F' ;Find F validation string MOV R3,#0 ;Start from the beginning BL box_findValid ;Find it CMP R2,#0 ;Was it not there? ADDEQ R13,R13,#40 ;No -- reset stack ptr LDMEQFD R13!,{R0,R1,R3-R5,PC}^ ;We did all we could ADR R0,box_hexdigits ;Point to hex digits table LDRB R0,[R0,R5] ;Get the right digit LDRB R5,[R2,#1] ;Get the old colour STRB R0,[R2,#1] ;Store in validation string SUB R2,R5,#'0' ;Turn into a digit CMP R2,#10 ;Is it a hex digit? SUBCS R2,R2,#7 ;Yes -- get the number CMP R2,#16 ;Is it still too big? SUBCS R2,R2,#&20 ;It must have been lower case ; --- Prod the icon into redrawing --- MOV R0,#0 ;Don't set either flags mask STR R0,[R1,#8] ;Set XOR mask STR R0,[R1,#12] ;Set BIC mask SWI XWimp_SetIconState ;Give the icon a little prod ADDVC R13,R13,#40 ;It worked fine LDMVCFD R13!,{R0,R1,R3-R5,PC}^ ;So return happily ADD R13,R13,#44 ;If it failed, reset stack LDMFD R13!,{R1,R3-R5,PC} ;And return the error ; --- Just set the colours in the time-honoured way --- 00box_setcolour MOV R2,#&F ;Only want 4 bits AND R2,R2,R0,LSR #28 ;Get old colour in R2 MOV R0,R5,LSL #28 ;Shift colour into position STR R0,[R1,#8] ;This is our XOR mask MOV R0,#&F0000000 ;Only change the colour STR R0,[R1,#12] ;This is our BIC mask SWI XWimp_SetIconState ;Give the icon a little prod ADDVC R13,R13,#40 ;It worked fine LDMVCFD R13!,{R0,R1,R3-R5,PC}^ ;So return happily ADD R13,R13,#44 ;If it failed, reset stack LDMFD R13!,{R1,R3-R5,PC} ;And return the error box_hexdigits DCB "0123456789ABCDEF",0 LTORG ;----- Messing with validation strings -------------------------------------- ; --- box_findValid --- ; ; On entry: R0 == pointer to icon block ; R2 == character to find in block (not case-sensitive) ; R3 == old pointer to search from, or 0 ; On exit: R3,R4 corrupted ; R2 points to command string if found, or 0 box_findValid ROUT STMFD R13!,{R3} ;Preserve for later use ; --- Ensure the icon is text and indirected --- LDR R3,[R0,#16] ;Get flags word TST R3,#1<<23 ;Is it deleted? MOVEQ R4,#&100 ;Can't put 101 in one instr ORREQ R4,R4,#&01 ;Check indirect and text ANDEQ R3,R3,R4 ;Mask the bits off CMPEQ R3,R4 ;Were they both set? MOVNE R2,#0 ;Couldn't find it ADDNE R13,R13,#4 MOVNES PC,R14 ;No -- return huffily ; --- Find the validation string --- LDR R3,[R0,#24] ;Get pointer to valid string CMP R3,#-1 ;Is it empty? MOVEQ R2,#0 ;Yes -- not found ADDEQ R13,R13,#4 MOVEQS PC,R14 ; --- Start from the right index --- ORR R2,R2,#&20 ;Make valid char lower case LDMFD R13!,{R4} ;Get search index STMFD R13!,{R14} ;Need another register CMP R4,#0 ;Is it the start? MOVNE R3,R4 ;No -- start from old pos BNE %02box_findValid ;And skip this command ; --- Check the first char of a validation string --- 00box_findValid LDRB R14,[R3],#1 ;Get a byte from string ORR R4,R14,#&20 ;Make lower case CMP R4,R2 ;Is it a match? SUBEQ R2,R3,#1 ;Point back to character LDMEQFD R13!,{PC}^ ;And return MOV R4,#0 ;Not an excaped character ; --- Skip ahead to the next validation string --- 01box_findValid CMP R14,#' ' ;Is it a control char? MOVCC R2,#0 ;Yes -- not found LDMCCFD R13!,{PC}^ ;And return CMP R4,#1 ;Are we escaping? MOVEQ R4,#0 ;Yes -- done that now BEQ %02box_findValid ;So skip this bit CMP R14,#';' ;Is it a semicolon? BEQ %00box_findValid ;Yes -- try a new command CMP R14,#'\' ;Is it a backslash? MOVEQ R4,#1 ;Yes -- escape next char 02box_findValid LDRB R14,[R3],#1 ;Get another character B %01box_findValid ;And try again LTORG ;----- Plot text+sprite icons ----------------------------------------------- ; --- box_plottns --- ; ; On entry: R0 == pointer to an icon block (writable) ; R2 == pointer to the validation string command ; R5-R10 == set up by box_readRectangle box_plottns ROUT STMFD R13!,{R0-R4,R14} ;Stack some registers ; --- Now copy the sprite name into the buffer --- LDR R0,[R13,#0] ;Find the icon pointer MOV R2,#'s' ;Find the sprite name MOV R3,#0 ;Search from the beginning BL box_findValid ;Find the string CMP R2,#0 ;Did it find anything? BEQ %99box_plottns ;No -- nothing to do then ; --- Copy the sprite name into the buffer --- ADR R0,s_buffer ;Point to my buffer ADD R2,R2,#1 ;Point to first sprite char 00box_plottns LDRB R14,[R2],#1 ;Get the character CMP R14,#';' ;Is it the string end? CMPNE R14,#',' ;Or the sprite name end? CMPNE R14,#&1F ;Or the validation string end MOVLS R14,#0 ;Yes -- null terminate STRB R14,[R0],#1 ;Store in the buffer BHI %00box_plottns ;No -- loop round again ; --- Now read the sprite information --- STMFD R13!,{R5,R6} ;Save some registers MOV R0,#40 ;Read sprite information LDR R1,s_sarea ;Find the user's sprite area ADR R2,s_buffer ;Point to the block CMP R1,#1 ;Is it the wimp area BEQ %f05 ;Yes -- skip on then ORR R0,R0,#&100 ;No -- say user sprite area SWI XOS_SpriteOp ;So try to cope with that BVC %f06 ;If OK skip onwards 05 MOV R0,#40 ;Read sprite information ADR R2,s_buffer ;Point to the block SWI XWimp_SpriteOp 06 MOV R0,R6 ;Get the sprite's mode number LDMFD R13!,{R5,R6} ;Unstack the registers BVS %99box_plottns ;No sprite, no text ; --- Find the width of the sprite, then --- MOV R1,#4 ;Read XEigFactor SWI XOS_ReadModeVariable ;Read the value then BVS %99box_plottns ;No sprite mode, no text MOV R4,R3,LSL R2 ;Get sprite width in OS units ; --- Plot the icon to avoid strangeness --- LDR R1,[R13,#0] ;Get the icon block pointer SWI XWimp_PlotIcon ;Plot the icon onto screen ; --- Copy the text string into the buffer --- LDR R2,[R13,#8] ;Find the validation string ADD R0,R2,#2 ;Point to the text string ADR R1,s_buffer ;Point to the buffer start 10box_plottns LDRB R14,[R0],#1 ;Get a byte from the string CMP R14,#'\' ;Is it an escape? BEQ %11box_plottns ;Yes -- handle it specially CMP R14,#';' ;Or the next command? CMPNE R14,#&1F ;Is it a control character MOVLS R14,#0 ;Yes -- store a null byte STRB R14,[R1],#1 ;Store the character away BHI %10box_plottns ;No -- loop round again B %12box_plottns ;Yes -- branch away 11box_plottns LDRB R14,[R0],#1 ;Get the escaped byte CMP R14,#32 ;Is it a control character? MOVCC R14,#0 ;Yes -- store a real term STRB R14,[R1],#1 ;Store the character away BCS %10box_plottns ;And get another one ; --- Now plot the text part --- 12box_plottns MOV R0,#8 ;Get the current font handle SWI XWimp_ReadSysInfo ;Go and do that then MOVVS R0,#0 ;If failed, assume system CMP R0,#0 ;Is there a magic font? LDR R1,[R13,#0] ;Find the icon block again LDR R0,[R1,#16] ;Find the icon flags word MOV R14,#&FF000000 ;Mask for the old flags ORRNE R14,R14,#&00400000 ;If antialiased, copy shade LDR R2,=&00000111 ;Magic flags for text part AND R0,R0,R14 ;Keep original colours ORR R0,R0,R2 ;Mix 'n' match the icon flags STR R0,[R1,#16] ;Store that back again LDR R0,[R1,#0] ;Get left icon edge ADD R0,R0,R4 ;Offset by the right amount STR R0,[R1,#0] ;Store it back again ADR R14,s_buffer ;Find the buffer pointer STR R14,[R1,#20] ;Point to the text string MOV R0,#-1 ;No validation string pliz STR R0,[R1,#24] ;Store it in the buffer SWI XWimp_PlotIcon ;And stick it on the screen ; --- Tidy up and leave --- 99box_plottns LDMFD R13!,{R0-R4,PC}^ ;Return to caller if OK LTORG ;----- Plot group boxes ----------------------------------------------------- ; --- box_plotgroup --- ; ; On entry: R0 == pointer to an icon block (writable) ; R2 == pointer to the validation string command ; R5-R10 == set up by box_readRectangle box_plotgroup ROUT STMFD R13!,{R0-R2,R14} ;Stack some registers ; --- Copy the string into the buffer --- LDR R2,[R13,#8] ;Find the validation string ADD R0,R2,#3 ;Point to the text string ADR R1,s_buffer ;Point to the buffer start 00box_plotgroup LDRB R14,[R0],#1 ;Get a byte from the string CMP R14,#'\' ;Is it an escape? BEQ %01box_plotgroup ;Yes -- handle it specially CMP R14,#';' ;Or the next command? CMPNE R14,#&1F ;Is it a control character MOVLS R14,#0 ;Yes -- terminate string STRB R14,[R1],#1 ;Store the character away BHI %00box_plotgroup ;No -- loop round again B %02box_plotgroup ;Yes -- branch away 01box_plotgroup LDRB R14,[R0],#1 ;Get the escaped byte CMP R14,#32 ;Is it a control character? MOVCC R14,#0 ;Yes -- store a real term STRB R14,[R1],#1 ;Store the character away BCS %00box_plotgroup ;And get another one ; --- Now plot the group border --- 02box_plotgroup LDR R0,[R13,#0] ;Get the icon block pointer LDRB R1,[R2,#2] ;Get the border type SUB R1,R1,#'0' ;Convert to an integer ADR R2,s_buffer ;Point to the string BL box_dogroup ;Handle the actual plotting ; --- Tidy up and leave --- 03box_plotgroup LDMFD R13!,{R0-R2,PC}^ ;Return to caller if OK LTORG ; --- box_dogroup --- ; ; On entry: R0 == pointer to coordinates box ; R1 == group border type number ; R2 == pointer to group title string box_dogroup ROUT STMFD R13!,{R11,R14} ;Store registers LDR R14,s_flags ;Get the flags word TST R14,#s_CHANNEL ;Does the user want channels? EORNE R1,R1,#1 ;Yes -- toggle channelness ADR R14,%02box_dogroup CMP R1,#(%02box_dogroup-%01box_dogroup)/4 ADDCC PC,PC,R1,LSL #2 ;Go to branch table LDMFD R13!,{R11,PC}^ ;Return to caller 01box_dogroup B grp0 ;Standard ridge and plinth B grp1 ;Acorn channel and gap B grp2 ;Standard ridge and plinth B grp3 ;Acorn channel and gap 02box_dogroup LDMFD R13!,{R11,PC} ;Return to caller ;----- Drawing group borders ------------------------------------------------ ; --- grp_titleicon --- ; ; On entry: R0 == pointer to icon coordinates to bodge ; R1 == left gap for icon title ; R2 == pointer to title string ; On exit: R0 == pointer to adjusted box grp_titleicon ROUT STMFD R13!,{R0-R5,R14} ;Stash registers away nicely ; --- Work out the length of the string --- MOV R5,#0 ;Nothing counted yet 00grp_titleicon LDRB R14,[R2,R5] ;Get the next character CMP R14,#32 ;Is it a control char? ADD R5,R5,#1 ;If not, bump the length BCS %00grp_titleicon ;And loop round again MOV R0,#8 ;Read the Wimp font handle SWI XWimp_ReadSysInfo ;Try and find it MOVVS R5,R5,LSL #4 ;Multiply by 16 BVS %01grp_titleicon ;If not supported, ignore CMP R0,#0 ;Is there a font used? MOVEQ R5,R5,LSL #4 ;Multiply by 16 BEQ %01grp_titleicon ;If not, skip ahead a bit ; --- Work out the width of the string --- MOV R1,#1000 ;Just something big MOV R2,#1000 ;Something else big :-) SWI XFont_Converttopoints ;Convert them to millipts SWI XFont_SetFont ;Set this as the current font MOV R3,R2 ;Move these coords now MOV R2,R1 LDR R1,[R13,#8] ;Find the string pointer MOV R4,#-1 ;Don't split the string SWI XFont_StringWidth ;Find the width of the string MOV R1,R2 ;Move the coords back again MOV R2,R3 SWI XFont_ConverttoOS ;Convert back to OS units ADD R5,R1,#16 ;Get the string width ; --- Now bodge the icon block --- 01grp_titleicon LDMIA R13,{R0,R1} ;Get block ptr and offset LDMIA R0,{R2,R3,R4,R14} ;Get the icon coords ADD R2,R2,R1 ;Offset the left side SUB R3,R14,#20 ;Find bottom of group box ADD R4,R2,R5 ;Add on the string width ADD R14,R14,#28 ;Find the top of the icon STMIA R0,{R2,R3,R4,R14} ;Store the modified coords ; --- Bodge the rest of the icon --- LDR R2,[R13,#8] ;Find the string pointer STR R2,[R0,#20] ;Store this as data MOV R2,#-1 ;No validation string STR R2,[R0,#24] ;Store this away too MOV R2,#1 ;It doesn't care about this STR R2,[R0,#28] ;Store this as the length LDR R2,=&17000139 ;Icon flags word STR R2,[R0,#16] ;Store this as icon flags LDMFD R13!,{R0-R5,PC}^ ;Return to caller ; --- grp_fillBorder --- ; ; On entry: R5-R8 == box coordinates (!) ; R9,R10 == window origin coordinates on the screen ; ; Removed in version 1.14 [ {FALSE} grp_fillBorder ROUT STMFD R13!,{R0-R4,R14} ;Save some registers MOV R0,#1 ;Grey background SWI XWimp_SetColour ;Set up the background MOV R0,#4 ;Move absolute ADD R1,R5,R9 ;Translate left hand side ADD R2,R6,R10 ;Translate bottom edge SWI XOS_Plot ;Move there MOV R0,#101 ;Filled rectangle, absolute ADD R1,R7,R9 ;Translate right hand side ADD R2,R8,R10 ;Translate top edge LDMIA R12,{R3,R4} ;Get the pixel sizes SUB R1,R1,R3 ;Chop a bit off the right SUB R2,R2,R4 ;Chop a bit off the top SWI XOS_Plot ;Fill in the background LDMFD R13!,{R0-R4,PC}^ ;Restore the registers LTORG ] ; --- grp 0 --- grp0 STMFD R13!,{R1-R8,R14} ;Stash registers LDMIA R0,{R5-R8} ;Get the border coordinates STMFD R13!,{R5-R8} ;Save them on the stack MOV R3,R0 ;Keep this pointer safe ; BL grp_fillBorder ;Don't fill in 1.14 ; --- Translate the icon block --- MOV R1,#16 ;Small offset here BL grp_titleicon ;Find the icon position ; --- Now display the main border --- LDMIA R0,{R5-R8} ;Save this position MOV R0,R13 ;Point to border position MOV R1,R3 ;Point to title position ADR R11,s_colours ;Point to colour table BL gborder ;Plot the group border ; --- Now display the main title border --- STMIA R3,{R5-R8} ;Restore saved position MOV R0,R3 ;Point to the position BL brd5 ;Plot the top plinth STMIA R0,{R5-R8} ;Restore that again MOV R1,R0 ;Point to the icon block SWI XWimp_PlotIcon ;Now plot the icon on top ADD R13,R13,#16 ;Restore stack pointer LDMFD R13!,{R1-R8,PC} ;Return to caller ; --- grp 1 --- grp1 STMFD R13!,{R1-R8,R14} ;Stash registers LDMIA R0,{R5-R8} ;Get the border coordinates STMFD R13!,{R5-R8} ;Save them on the stack MOV R3,R0 ;Keep this pointer safe ; --- Translate the icon block --- MOV R1,#16 ;Small offset here BL grp_titleicon ;Find the icon position ; --- Now display the main border --- LDMIA R0,{R5-R8} ;Save this position MOV R0,R13 ;Point to border position MOV R1,R3 ;Point to title position LDR R11,s_flags ;Get the flags word TST R11,#s_FAINTCHAN ;Is it meant to be faint ADREQ R11,s_colours+1 ;Point to colour table ADRNE R11,s_shadeCols+1 BL gborder ;Plot the group border ; --- Now display the main title border --- STMIA R3,{R5-R8} ;Restore saved position MOV R0,R3 ;Point to the position BL brd6 ;Plot the top thingy STMIA R0,{R5-R8} ;Restore that again MOV R1,R0 ;Point to the icon block ; --- Stop the top bit from being filled --- LDR R0,[R1,#16] BIC R0,R0,#(1<<5) ;Clear filled flag STR R0,[R1,#16] SWI XWimp_PlotIcon ;Now plot the icon on top ADD R13,R13,#16 ;Restore stack pointer LDMFD R13!,{R1-R8,PC} ;Return to caller ; --- grp 2 --- grp2 STMFD R13!,{R1-R8,R14} ;Stash registers LDMIA R0,{R5-R8} ;Get the border coordinates STMFD R13!,{R5-R8} ;Save them on the stack MOV R3,R0 ;Keep this pointer safe ; BL grp_fillBorder ;Don't fill in 1.14 ; --- Translate the icon block --- MOV R1,#32 ;Large offset here BL grp_titleicon ;Find the icon position ; --- Now display the main border --- LDMIA R0,{R5-R8} ;Save this position MOV R0,R13 ;Point to border position MOV R1,R3 ;Point to title position ADR R11,s_colours ;Point to colour table BL gborder ;Plot the group border ; --- Now display the main title border --- STMIA R3,{R5-R8} ;Restore saved position MOV R0,R3 ;Point to the position BL brd5 ;Plot the top plinth STMIA R0,{R5-R8} ;Restore that again MOV R1,R0 ;Point to the icon block SWI XWimp_PlotIcon ;Now plot the icon on top ADD R13,R13,#16 ;Restore stack pointer LDMFD R13!,{R1-R8,PC} ;Return to caller ; --- grp 3 --- grp3 STMFD R13!,{R1-R8,R14} ;Stash registers LDMIA R0,{R5-R8} ;Get the border coordinates STMFD R13!,{R5-R8} ;Save them on the stack MOV R3,R0 ;Keep this pointer safe ; --- Translate the icon block --- MOV R1,#32 ;Small offset here BL grp_titleicon ;Find the icon position ; --- Now display the main border --- LDMIA R0,{R5-R8} ;Save this position MOV R0,R13 ;Point to border position MOV R1,R3 ;Point to title position LDR R11,s_flags ;Get the flags word TST R11,#s_FAINTCHAN ;Is it meant to be faint ADREQ R11,s_colours+1 ;Point to colour table ADRNE R11,s_shadeCols+1 BL gborder ;Plot the group border ; --- Now display the main title border --- STMIA R3,{R5-R8} ;Restore saved position MOV R0,R3 ;Point to the position BL brd6 ;Plot the top thingy STMIA R0,{R5-R8} ;Restore that again MOV R1,R0 ;Point to the icon block ; --- Stop the top bit from being filled --- LDR R0,[R1,#16] BIC R0,R0,#(1<<5) ;Clear filled flag STR R0,[R1,#16] SWI XWimp_PlotIcon ;Now plot the icon on top ADD R13,R13,#16 ;Restore stack pointer LDMFD R13!,{R1-R8,PC} ;Return to caller ; --- gborder --- ; ; On entry: R0 == pointer to icon coordinates block (writable) ; R1 == pointer to title icon coordinate ; R9 == x coord of window origin on screen ; R10 == y coord of window origin on screen ; ; Plots a group border such that it doesn't overlap the title icon at all. gborder ROUT STMFD R13!,{R0-R5,R8,R14} ;Stack registers away MOV R8,R1 ;Keep this pointer safe ; --- Now convert all the boxes to screen coords --- LDMIA R0,{R1-R4} ;Get the straight box BL box_convert STMIA R0,{R1-R4} ;Write it back nicely SUB R1,R1,#4 ;Now expand it a little SUB R2,R2,#4 ADD R3,R3,#4 ADD R4,R4,#4 STMFD R13!,{R1-R4} ;Stash them on the stack LDMIA R8,{R1-R4} ;Get the title position BL box_convert STMFD R13!,{R1-R4} ;Save them on the stack too ; --- Now render all the parts except for the top --- MOV R1,R0 LDRB R0,[R11,#0] SWI XWimp_SetColour ADD R0,R13,#16 BL prim_left MOV R0,R1 BL prim_right LDRB R0,[R11,#1] SWI XWimp_SetColour ADD R0,R13,#16 BL prim_right BL prim_bottom MOV R0,R1 BL prim_left LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_bottom ; --- Now fix up the top coordinates --- LDR R0,[R13,#8] ;Get right side of title box ADD R0,R0,#8 ;Move it clear of the group LDR R5,[R1,#0] ;Get the old left hand side STR R0,[R1,#0] ;Store as left side here STR R0,[R13,#16] ;And left side for other one ; --- Now render the left top sides --- ADD R0,R13,#16 BL prim_top LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R1 BL prim_top ; --- Now get the right top sides --- STR R5,[R1,#0] ;Store it back again SUB R5,R5,#4 ;Fiddle for outer border STR R5,[R13,#16] ;Save in outer border block LDR R0,[R13,#0] ;Get right hand side of this SUB R0,R0,#4 ;Move it over a little STR R0,[R1,#8] ;Store as rightside here STR R0,[R13,#24] ;And right side for other one ; --- Now render the right top sides --- MOV R0,R1 BL prim_top LDRB R0,[R11,#0] SWI XWimp_SetColour ADD R0,R13,#16 BL prim_top ; --- Return -- it's all over --- ADD R13,R13,#32 ;Restore the stack pointer LDMFD R13!,{R0-R5,R8,PC}^ ;Return to caller LTORG ;----- Draw the border types ------------------------------------------------ ; ; All entry: R0 == pointer to icon coordinates block (writable) ; R9 == x coord of window origin on screen ; R10 == y coord of window origin on screen ; --- brd8 --- brd8 ROUT STMFD R13!,{R14} LDR R14,s_flags TST R14,#s_FAINTCHAN ANDNE R14,R11,#3 ADRNE R11,s_shadeCols ADDNE R11,R11,R14 LDMFD R13!,{R14} ; --- brd0 --- brd0 ROUT STMFD R13!,{R0-R4,R14} ;Stack registers away LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMIA R0,{R1-R4} MOV R1,R0 ;Keep pointer to box ; --- Draw bits of the border --- LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_left LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R1 BL prim_right BL prim_bottom LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_top LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- brd1 --- brd1 ROUT STMFD R13!,{R0-R4,R14} ;Stack registers away SUB R13,R13,#16 ;Make space for another blk LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMIA R0,{R1-R4} SUB R1,R1,#4 SUB R2,R2,#4 ADD R3,R3,#4 ADD R4,R4,#4 STMIA R13,{R1-R4} MOV R1,R0 ;Keep pointer to box ; --- Draw bits of the border --- LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R13 BL prim_left MOV R0,R1 BL prim_right LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R13 BL prim_right BL prim_bottom MOV R0,R1 BL prim_left BL prim_top LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R13 BL prim_top MOV R0,R1 BL prim_bottom ADD R13,R13,#16 LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- brd2 --- brd2 ROUT STMFD R13!,{R0-R4,R14} ;Stack registers away LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMIA R0,{R1-R4} SUB R1,R1,#4 SUB R2,R2,#4 ADD R3,R3,#4 ADD R4,R4,#4 STMFD R13!,{R1-R4} SUB R1,R1,#4 SUB R2,R2,#4 ADD R3,R3,#4 ADD R4,R4,#4 STMFD R13!,{R1-R4} MOV R1,R0 ;Keep pointer to box ; --- Draw inside border --- LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_left LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R1 BL prim_right BL prim_bottom LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_top ; --- Draw rim around the middle --- ; ; It's overkill, but I'll use the calls below for this LDR R0,s_rimcol SWI XWimp_SetColour ADD R0,R13,#16 BL prim_left BL prim_right BL prim_top BL prim_bottom ; --- Draw surrounding border --- BIC R11,R11,#1 ;Round pointer downwards LDR R0,[R11,#1] SWI XWimp_SetColour MOV R0,R13 BL prim_left LDR R0,[R11,#0] SWI XWimp_SetColour MOV R0,R13 BL prim_right BL prim_bottom LDR R0,[R11,#1] SWI XWimp_SetColour MOV R0,R13 BL prim_top ADD R13,R13,#32 LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- brd3 --- brd3 ROUT STMFD R13!,{R0-R4,R14} ;Stack registers away LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMIA R0,{R1-R4} MOV R1,R0 ;Save this away ; --- Fill in the inside section to overwrite marbling --- MOV R0,#1 SWI XWimp_SetColour MOV R0,R1 BL prim_left BL prim_right BL prim_bottom BL prim_top LDMIA R0,{R1-R4} SUB R1,R1,#4 SUB R2,R2,#4 ADD R3,R3,#4 ADD R4,R4,#4 STMIA R0,{R1-R4} MOV R1,R0 ;Keep pointer to box ; --- Draw bits of the border --- LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R1 BL prim_left LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_right BL prim_bottom LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R1 BL prim_top LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- brd5 --- brd5 ROUT STMFD R13!,{R0-R4,R14} ;Stack registers away LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMIA R0,{R1-R4} SUB R14,R4,R2 ;Get height of box ADD R2,R2,R14,LSR #1 ;Centre R2 in box SUB R4,R2,#4 ;Move thing to right place ADD R2,R2,#4 ;And copy across SUB R3,R1,#4 ;Set up the nick width STMFD R13!,{R1-R4} ;Stash them on the stack MOV R1,R0 ;Keep pointer to box ; --- Draw bits of the border --- LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_left LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R1 BL prim_right BL prim_bottom MOV R0,R13 BL prim_top LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R1 BL prim_top LDMIA R1,{R1-R3} LDR R2,[R13,#4] ADD R1,R3,#4 STMIA R13,{R1-R3} MOV R0,R13 BL prim_bottom ADD R13,R13,#16 LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- brd6 --- brd6 ROUT STMFD R13!,{R0-R4,R14} ;Stack registers away LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMIA R0,{R1-R4} SUB R14,R4,R2 ;Get height of box ADD R2,R2,R14,LSR #1 ;Centre R2 in box MOV R4,R2 ;Move thing to right place SUB R3,R1,#4 ;Set up the nick width STMFD R13!,{R1-R4} ;Stash them on the stack MOV R1,R0 ;Keep pointer to box ; --- Draw bits of the border --- LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R13 BL prim_left LDRB R0,[R11,#0] SWI XWimp_SetColour MOV R0,R13 BL prim_top LDMIA R1,{R1-R3} LDR R2,[R13,#4] ADD R1,R3,#4 STMIA R13,{R1-R3} BL prim_right LDRB R0,[R11,#1] SWI XWimp_SetColour MOV R0,R13 BL prim_bottom ADD R13,R13,#16 LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- brd7 --- brd7 ROUT STMFD R13!,{R0-R10,R14} ;Stack registers away LDMIA R0,{R1-R4} ;Load the coordinates BL box_convert STMFD R13!,{R1-R4} MOV R10,R0 ;Save this away LDR R9,[R10,#16] ;Load the icon's flags ; --- Find out about the icon's colours --- TST R9,#1<<6 ;Is it anti-aliased? BEQ %10brd7 ;No -- skip this bit out then BIC R9,R9,#&ff000000 ;Clear out the font handle MOV R2,#'F' ;Find font validation strings MOV R3,#0 ;Start from the beginning BL box_findValid ;Find the colour command CMP R2,#0 ;Was it not there at all? ORREQ R9,R9,#&07000000 ;No -- use default colours BEQ %10brd7 ;And skip to the end LDRB R0,[R2,#1] ;Load a byte from the string SUB R0,R0,#'0' ;Turn it into a number CMP R0,#10 ;Is it a letter, not a digit? SUBCS R0,R0,#7 ;Yes -- compensate for that CMP R0,#16 ;Is it lowercase? SUBCS R0,R0,#&20 ;Yes -- deal with that case LDRB R1,[R2,#2] ;Load the next byte too SUB R1,R1,#'0' ;Turn it into a number CMP R1,#10 ;Is it a letter, not a digit? SUBCS R1,R1,#7 ;Yes -- compensate for that CMP R1,#16 ;Is it lowercase? SUBCS R1,R1,#&20 ;Yes -- deal with that case ORR R9,R9,R0,LSL #28 ;Fit the background colour in ORR R9,R9,R1,LSL #24 ;And the foreground colour ; --- First plot the whole background --- 10brd7 ADR R14,s_dx ;Point to the pixel sizes LDMIA R14,{R7,R8} ;Load them out nicely LDMFD R13!,{R3-R6} ;Load the coordinates out TST R9,#1<<5 ;Is the icon filled? BEQ %20brd7 ;No -- skip this bit out MOV R0,R9,LSR #28 ;Get the background colour AND R0,R0,#&f ;Clear all the other bits SWI XWimp_SetColour ;Set the bit's colour MOV R0,#plot_MOVE+plot_ABSOLUTE SUB R1,R3,#4 SUB R2,R4,#4 ADD R1,R1,R7 ;Don't overlap the border ADD R2,R2,R8 SWI XOS_Plot ;Move to the bottom left MOV R0,#plot_RECTFILL+plot_ABSOLUTE+plot_FORE ADD R1,R5,#4 ADD R2,R6,#4 SUB R1,R1,R7,LSL #1 SUB R2,R2,R8,LSL #1 SWI XOS_Plot ;Fill in the background ; --- Plot the foreground border now --- 20brd7 MOV R0,R9,LSR #24 ;Get the foreground colour AND R0,R0,#&f ;Clear all the other bits SWI XWimp_SetColour ;Set the bit's colour MOV R0,#plot_MOVE+plot_ABSOLUTE SUB R1,R3,#4 SUB R2,R4,#4 SWI XOS_Plot ;Move to the bottom left MOV R0,#plot_LINE+plot_ABSOLUTE+plot_FORE ADD R1,R5,#4 SUB R1,R1,R7 SUB R2,R4,#4 SWI XOS_Plot ;Plot the left hand side MOV R0,#plot_LINE+plot_ABSOLUTE+plot_FORE ADD R1,R5,#4 SUB R1,R1,R7 ADD R2,R6,#4 SUB R2,R2,R8 SWI XOS_Plot ;Plot the top edge MOV R0,#plot_LINE+plot_ABSOLUTE+plot_FORE SUB R1,R3,#4 ADD R2,R6,#4 SUB R2,R2,R8 SWI XOS_Plot ;Plot the right hand side MOV R0,#plot_LINE+plot_ABSOLUTE+plot_FORE SUB R1,R3,#4 SUB R2,R4,#4 SWI XOS_Plot ;Plot the bottom edge ; --- Now plot a writable border (type 3) --- LDMIA R10,{R0-R3} ;Load the coordinates SUB R0,R0,#4 ;Modify for the extra border SUB R1,R1,#4 ADD R2,R2,#4 ADD R3,R3,#4 STMIA R10,{R0-R3} LDMFD R13!,{R0-R10,R14} ;Restore all the registers B brd3 ;And plot the writable border LTORG ;----- Mangle coordinates for the mode -------------------------------------- ; --- box_convert --- ; ; Converts box given in R1-R4 by translating to screen coords and rounding ; down to pixel boundaries box_convert ROUT STMFD R13!,{R0,R14} ;Stash registers ; --- Convert to screen coordinates --- ADD R1,R1,R9 ADD R2,R2,R10 ADD R3,R3,R9 ADD R4,R4,R10 ; --- Round off to whole pixel sizes --- LDR R0,s_dx LDR R14,s_dy SUB R0,R0,#1 SUB R14,R14,#1 BIC R1,R1,R0 BIC R2,R2,R14 BIC R3,R3,R0 BIC R4,R4,R14 LDMFD R13!,{R0,PC} ;----- Set up the VDU variables in the buffer ------------------------------- ; --- vdu_set --- vdu_set ROUT STMFD R13!,{R0-R3,R14} ;Stack some registers ADR R0,vdu_wanted ;Which ones do we want? ADR R1,s_dx ;Where do we want them? SWI XOS_ReadVduVariables ;Read the values LDMIA R1,{R0,R2} ;Read their values into regs CMP R2,#2 ;Is this a high-pixel mode? MOVEQ R3,#2 ;Yes -- use a default value MOVNE R3,#4 MOVNE R3,R3,LSR R2 ;No -- divide up border RSBNE R3,R3,#4 MOV R14,#1 MOV R0,R14,LSL R0 ;Convert these to pixel sizes MOV R2,R14,LSL R2 STMIA R1,{R0,R2,R3} ;Store back in workspace LDMFD R13!,{R0-R3,PC}^ ;Return to caller vdu_wanted DCD vdu_XEIG DCD vdu_YEIG DCD -1 LTORG ;----- Plot primitives ------------------------------------------------------ ; --- prim_left --- ; ; Plots a vertical strip in the current foreground colour on the left of an ; icon box. ; ; On entry: R0 == pointer to the icon bounding box prim_left ROUT STMFD R13!,{R0-R3,R14} ;Keep the stack pointer busy MOV R3,R0 ;Keep the pointer safe LDMIA R3!,{R1,R2} ;Get the bottom left coord SUB R1,R1,#4 ;Make way for the border SUB R2,R2,#4 ;Make way for the border MOV R0,#plot_MOVE+plot_ABSOLUTE SWI XOS_Plot ;Move to first corner LDR R1,s_dx ;Get the pixel width RSB R1,R1,#4 ;Trim the width a little LDR R3,[R3,#4] ;Get the top coordinate SUB R2,R3,R2 ;Find the height of the strip LDR R3,s_dy ;Get the y pixel size SUB R2,R2,R3 ;And add that in too ADD R2,R2,#4 ;And add the border width MOV R0,#plot_RECTFILL+plot_FORE+plot_RELATIVE SWI XOS_Plot ;Plot the rectangle LDMFD R13!,{R0-R3,PC}^ ;Return to caller LTORG ; --- prim_right --- ; ; Plots a vertical strip in the current foreground colour on the right of an ; icon box. ; ; On entry: R0 == pointer to the icon bounding box prim_right ROUT STMFD R13!,{R0-R3,R14} ;Keep the stack pointer busy ADD R3,R0,#16 ;Point to the top of the box LDMDB R3!,{R1,R2} ;Get the top right coord LDR R0,s_dy ;Get the y pixel size SUB R2,R2,R0 ADD R2,R2,#4 ;Make way for the border MOV R0,#plot_MOVE+plot_ABSOLUTE SWI XOS_Plot ;Move to first corner LDR R1,s_dx ;Get the pixel width RSB R1,R1,#4 ;Trim the width a little LDR R3,[R3,#-4] ;Get the bottom coordinate SUB R2,R3,R2 ;Find the height of the strip SUB R2,R2,#4 ;And add the border width MOV R0,#plot_RECTFILL+plot_FORE+plot_RELATIVE SWI XOS_Plot ;Plot the rectangle LDMFD R13!,{R0-R3,PC}^ ;Return to caller LTORG ; --- prim_bottom --- ; ; Plots a horizontal strip in the current foreground colour along the bottom ; of an icon, with a little jagged bit on the left hand side. ; ; On entry: R0 == pointer to icon block prim_bottom ROUT STMFD R13!,{R0-R2,R7-R11,R14} ;Keep stack pointer moving ; --- Load the variables we need --- LDMIA R0,{R9-R11} ;Get useful coordinates out LDR R1,s_dx ;Get x pixel width LDR R8,s_dy ;Get y pixel width LDR R2,s_start ;Get start X offset ; --- Initialise variables for first loop --- SUB R9,R9,R2 ;Shift x0 back a little SUB R11,R11,R1 ;Shift x1 past icon edge SUB R2,R10,R8 ;Move y below the icon ADD R11,R11,#4 ;And make space for border RSB R7,R8,#4 ;Loop stops when R7==0 ; --- Draw a line (loop body) --- 00prim_bottom MOV R0,#plot_MOVE+plot_ABSOLUTE MOV R1,R9 SWI XOS_Plot ;Move to the left of the line MOV R0,#plot_LINE+plot_FORE+plot_ABSOLUTE MOV R1,R11 SWI XOS_Plot ;Draw the line ; --- Check if we've done (loop termination) --- SUBS R7,R7,R8 ;Decrement the counter LDMLTFD R13!,{R0-R2,R7-R11,PC}^ ;Return to caller ; --- Update coordinates (loop update) --- SUB R9,R9,R8 ;Move x coordinate back a bit SUB R2,R2,R8 ;Move y coordinate down a bit B %00prim_bottom ;And do it all again LTORG ; --- prim_top --- ; ; Plots a horizontal strip in the current foreground colour along the top ; of an icon, with a little jagged bit on the right hand side. ; ; On entry: R0 == pointer to icon block prim_top ROUT STMFD R13!,{R0-R2,R7-R11,R14} ;Keep stack pointer moving ; --- Load the variables we need --- LDMIA R0,{R8-R11} ;Get useful coordinates out MOV R9,R8 ;Don't want y0 LDR R1,s_dx ;Get x pixel width LDR R8,s_dy ;Get y pixel width LDR R2,s_start ;Get start X offset ; --- Initialise variables for first loop --- SUB R9,R9,#4 ;Make space for border SUB R10,R10,R1 ;Shift x1 past icon edge ADD R10,R10,R2 ;And add on the little bitty MOV R2,R11 ;Move y above the icon RSB R7,R8,#4 ;Loop stops when R7==0 ; --- Draw a line (loop body) --- 00prim_top MOV R0,#plot_MOVE+plot_ABSOLUTE MOV R1,R9 SWI XOS_Plot ;Move to the left of the line MOV R0,#plot_LINE+plot_FORE+plot_ABSOLUTE MOV R1,R10 SWI XOS_Plot ;Draw the line ; --- Check if we've done (loop termination) --- SUBS R7,R7,R8 ;Decrement the counter LDMLTFD R13!,{R0-R2,R7-R11,PC}^ ;Return to caller ; --- Update coordinates (loop update) --- ADD R10,R10,R8 ;Move x coordinate on a bit ADD R2,R2,R8 ;Move y coordinate up a bit B %00prim_top ;And do it all again LTORG ;----- Workspace layout ----------------------------------------------------- ^ 0,R12 s_wstart # 0 ; --- Graphics variables --- s_dx # 4 ;Horizontal pixel size (OS) s_dy # 4 ;Vertical pixel size (OS) s_start # 4 ;Offset into corner for plot ; --- Various other things --- s_flags # 4 ;Various Sculptix flags s_sarea # 4 ;The sprite area in tns icons ; --- Colours --- s_colours # 4 ;Colours for the 3D bits s_shadeCols # 4 ;Colours for shaded 3D boxes s_slabcol # 1 ;Slabbing in colour s_rimcol # 1 ;Inner rim colour for type 2 # 2 ;Padding to align ; --- Misc buffers --- s_buffer # 256 ;A big buffer for things s_wend # 0 s_UNSLAB EQU (1<<0) ;We've unslabbed this poll s_CHANNEL EQU (1<<1) ;Use channels, not ridges s_FAINTCHAN EQU (1<<2) ;Draw channel boxes faintly s_wsize EQU s_wend-s_wstart ;----- That's all, folks ---------------------------------------------------- END