; ; border.s ; ; Plots borders given an icon block and a definition of the border shape ; ; © 1995-1998 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. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sh.colours GET sh.wSpace GET sh.messages ;----- The idea ------------------------------------------------------------- ; ; We store the border shapes as commands in blocks, and then read them out ; when plotting needs to be done. ; ; The commands are very simple, and are one byte wide each. Some commands ; have arguments which are stored in the following byte or word. Whole ; word arguments are preceded by padding to a word boundary. It ends up ; looking a bit like a simple `machine code'. ;----- Main code ------------------------------------------------------------ AREA |Module$$Code|,CODE,READONLY ; --- border_plot --- ; ; On entry: R0 == pointer to border defintion ; R1 == pointer to icon block ; R2,R3 == window origin position ; R4 == pointer to colour table ; R5 == group box title width (optional) ; R6 == group box title address (optional) ; ; On exit: May return an error ; ; Use: Plots a border using the border definition. EXPORT border_plot border_plot ROUT STMFD R13!,{R0-R11,R14} ;Save lots of registers ; --- Set up some environment --- MOV R10,R0 ;Point at the border routine ADR R14,sculpt_vduVars ;Point to the VDU variables LDMIA R14,{R7-R9} ;Load these for the rule rtns LDMIA R1,{R4-R6,R14} ;Load the icon position SUB R0,R7,#1 ;Turn this into a bitmask BIC R4,R4,R0 ;Mask the x coordinates BIC R6,R6,R0 ;To avoid nasty problems SUB R0,R8,#1 ;Turn this into a bitmask BIC R5,R5,R0 ;Mask the y coordinates BIC R14,R14,R0 ;To avoid nasty problems ADD R4,R4,R2 ;Convert to screen coords ADD R5,R5,R3 ;Convert to screen coords ADD R6,R6,R2 ;Convert to screen coords ADD R14,R14,R3 ;Convert to screen coords STMFD R13!,{R4-R6,R14} ;These are initial reg values MOV R11,R13 ;Remember this position ; --- Now start executing --- border__main LDRB R14,[R10],#1 ;Load the next instruction AND R0,R14,#3 ;Fetch immediate op bits BIC R14,R14,#3 ;Clear them from the byte CMP R14,#(%10-%00) ;Is instruction known? ADDCC PC,PC,R14 ;Yes -- dispatch it then B %10border_plot ;If unknown, report error 00 B border__ret ;End the routine B border__iLoad ;Load a value from the icon B border__load ;Load a stored value B border__ldCtr ;Load a centrepoint B border__op ;Do an op on the value B border__store ;Store value in output blk B border__stdCol ;Standard colour selection B border__colour ;Other colour ops B border__plot ;Plot a rule B border__skipTtl ;Skip over the group title B border__plotGrp ;Plot a group box B border__call ;Call a subroutine 10border_plot ADRL R0,msg_errBadOpcode ;Point to the error message ADD R13,R11,#16+4 ;Restore the stack pointer LDMFD R13!,{R1-R11,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return the error ; --- border__ret --- border__ret CMP R13,R11 ;Are we at top level? LDMCCFD R13!,{R10} ;No -- restore our IP BCC border__main ;And continue ADD R13,R11,#16 ;Restore stack pointer LDMFD R13!,{R0-R11,R14} ;Restore registers BICS PC,R14,#V_flag ;And return with glad tidings ; --- border__iLoad --- border__iLoad LDR R6,[R1,R0,LSL #2] ;Load the requested value border__round TST R0,#1 ;Is this a y-coordinate? ADDEQ R6,R6,R2 ;No -- adjust by x origin ADDNE R6,R6,R3 ;Yes -- adjust by y origin SUBEQ R14,R7,#1 ;No -- get x width SUBNE R14,R8,#1 ;Yes -- get y width BIC R6,R6,R14 ;Round the value nicely B border__main ;And get next instruction ; --- border__load --- border__load LDR R6,[R11,R0,LSL #2] ;Load the requested value B border__main ;And get the next instruction ; --- border__ldCtr --- border__ldCtr ADD R14,R1,R0,LSL #2 ;Find the correct bit LDMIA R14,{R5,R6,R14} ;Load three values ADD R6,R5,R14 ;Add the two together MOV R6,R6,ASR #1 ;Divide by two B border__round ;Now round the value to pixel ; --- border__op --- border__op LDRB R14,[R10],#1 ;Load the next byte out TST R0,#1 ;Which op is it? ADDEQ R6,R6,R14 ;Add -- do the add then SUBNE R6,R6,R14 ;Sub -- do that B border__main ;And skip off merrily ; --- border__store --- border__store STR R6,[R11,R0,LSL #2] ;Store it (can't trash stk) B border__main ;And return to loop ; --- border__stdCol --- border__stdCol TST R0,#2 ;Doing complicated things? BNE %f00 ;Yes -- skip forwards then LDR R14,[R11,#16 + 4*4] ;Load the colour table addr LDRB R0,[R14,R0] ;Load the colour out SWI XWimp_SetColour ;Do the set B border__main ;And loop back round 00 LDR R14,[R11,#16 + 4*4] ;Load the colour table addr BIC R14,R14,#&03 ;Clear non-alignedness STR R14,[R11,#16 + 4*4] ;Store the address back B border__main ;And return to caller ; --- border__colour --- border__colour CMP R0,#0 ;Is this set-from-icon? BEQ %f00 ;Yes -- do this CMP R0,#1 ;Do we indirect this? LDRB R0,[R10],#1 ;Load the argument byte LDREQB R0,[R12,R0] ;Load the colour out SWI XWimp_SetColour ;Set the colour B border__main ;And loop back for more 00 BL colours_read ;Read the colours out MOV R4,R0,LSR #4 ;Extract background colour AND R0,R0,#&F ;Extract foreground colour LDR R14,[R1,#16] ;Load the icon flags, please TST R14,#&00400000 ;Is icon /really/ shaded? ANDNE R0,R0,#2 ;Yes -- shade in simple way SWI XWimp_SetColour ;Set the colour, please ORR R0,R4,#&80 ;Get the background colour SWI XWimp_SetColour ;Set the colour, please B border__main ;And continue ; --- border__plot --- border__plot ADD R10,R10,#4+3 ;Word align instruction ptr BIC R10,R10,#3 ;And advance past the branch STMFD R13!,{R1-R3,R6} ;Store useful values LDMIA R11,{R3-R6} ;Load the coordinates MOV R14,PC ;Set up return address SUB PC,R10,#4 ;Call the branch instr LDMFD R13!,{R1-R3,R6} ;Restore the registers B border__main ;And rejoin the loop ; --- border__skipTtl --- border__skipTtl LDR R14,[R11,#16 + 4*5] ;Load the title width ADD R6,R6,R14 ;Add this on nicely SUB R14,R7,#1 ;Get x bitmask BIC R6,R6,R14 ;To be nice B border__main ;Go forth and execute ; --- border__plotGrp --- border__plotGrp LDMIA R11,{R4-R6,R14} ;Load the coordinates SUB R4,R4,R2 ;Make them window relative SUB R5,R5,R3 ;Keep doing this a bit SUB R6,R6,R2 SUB R14,R14,R3 SUB R13,R13,#32 ;Make space for the block STMIA R13,{R4-R6,R14} ;Store all them away ADD R10,R10,#4+3 ;Word align instruction ptr BIC R10,R10,#3 ;And skip past flags word LDR R4,[R10,#-4] ;Load the flags word LDR R5,[R1,#16] ;Load the original flags BIC R4,R4,#&0F400000 ;Clear the static flags AND R5,R5,#&0F400000 ;And mask the real flags ORR R4,R4,R5 ;Combine them nicely LDR R5,[R11,#16 + 4*6] ;Get the title MOV R6,#-1 ;No validation string MOV R14,#1 ;A random buffer length ADD R0,R13,#16 ;Find a space nicely STMIA R0,{R4-R6,R14} ;Save the icon data MOV R1,R13 ;Point to this block SWI XWimp_PlotIcon ;Do the icon plotting ADD R13,R13,#32 ;Restore the stack pointer LDR R1,[R11,#16 + 4*1] ;Reload the icon pointer B border__main ;Done that ; --- border__call --- border__call ADD R10,R10,#4+3 ;Word align instruction ptr BIC R10,R10,#3 ;And advance past the branch TST R0,#1 ;Do we save the old one? STMNEFD R13!,{R10} ;Yes -- save old IP on stack LDR R14,[R10,#-4] ;Load the branch offset ADD R10,R10,R14 ;Find the new routine B border__main ;Continue executing subrt LTORG ;----- Command codes -------------------------------------------------------- ; ; We try to organise these in a way which makes it easy to decode. The ; bottom two bits end up as an immediate operand in most cases, allowing us ; to select entries in the icon bounding box easily. ^ -4 # 4 bCmd_ret EQU {VAR} ;End border operation # 4 bCmd_ldix0 EQU {VAR}+0 ;Fetch X0 of the icon bCmd_ldiy0 EQU {VAR}+1 ;Fetch Y0 of the icon bCmd_ldix1 EQU {VAR}+2 ;Fetch X1 of the icon bCmd_ldiy1 EQU {VAR}+3 ;Fetch Y1 of the icon # 4 bCmd_ldx0 EQU {VAR}+0 ;Fetch last stored X0 bCmd_ldy0 EQU {VAR}+1 ;Fetch last stored Y0 bCmd_ldx1 EQU {VAR}+2 ;Fetch last stored X1 bCmd_ldy1 EQU {VAR}+3 ;Fetch last stored Y1 # 4 bCmd_ldhc EQU {VAR}+0 ;Fetch horizontal centre bCmd_ldvc EQU {VAR}+1 ;Fetch vertical centre # 4 bCmd_add EQU {VAR}+0 ;Add next byte bCmd_sub EQU {VAR}+1 ;Subtract next byte # 4 bCmd_stx0 EQU {VAR}+0 ;Store as the X0 parameter bCmd_sty0 EQU {VAR}+1 ;Store as the Y0 parameter bCmd_stx1 EQU {VAR}+2 ;Store as the X1 parameter bCmd_sty1 EQU {VAR}+3 ;Store as the Y1 parameter # 4 bCmd_dark EQU {VAR}+0 ;Use the current `dark' col bCmd_light EQU {VAR}+1 ;Use the current `light' col bCmd_raw EQU {VAR}+2 ;Switch to uninverted colours # 4 bCmd_icon EQU {VAR}+0 ;Set colours from icon bCmd_indCol EQU {VAR}+1 ;Indirected colour bCmd_litCol EQU {VAR}+2 ;Literal colour # 4 bCmd_plot EQU {VAR}+0 ;Plot a rule (arg == branch) # 4 bCmd_skpt EQU {VAR}+0 ;Skip past the `title' # 4 bCmd_group EQU {VAR}+0 ;Plot a group box # 4 bCmd_jmp EQU {VAR}+0 ;Jump to a routine bCmd_call EQU {VAR}+1 ;Call subroutine ;----- That's all, folks ---------------------------------------------------- END