A következő szkript tesztelése (és javítása) után az ERM Debugger jön, utána pedig a KARAVÁN. Hexadecimális/bináris számokat kedvelő tesztelőket várok. Esős téli estékre számítva bemásolom:
-----------------------------------------------------------------------------------------
ZVSE
ERMS_ScriptName=Limited ERM Debugger- Script129
ERMS_ScriptAuthor=Doom3d
ERMS_ScriptVersion=0.0.0
ERMS_ScriptDate=18.11(November).2006
ERMS_ScriptERMVersion=2.70
ERMS_ScriptLanguage=English or Magyar (native)
ERMS_ScriptUsedVariables=shared1460-1491(readonlylookuptable);v258-262;v313-319
ERMS_ScriptUsedFlags=-
ERMS_ScriptUsedTimers=-
ERMS_ScriptUsedFunctions=FU644-647
ERMS_ScriptUsedMacroNames=-
_WARNING_#1=IMPORTANT! This file is not in a plain text format. NEVER use any editor except ERM_S for making any kind of changes!
ERMS_PoweredBy=ERM Scripter v. 2004.10.5.945
ERMS_AdditionalFiles=
* | (or= alt+w on my keyboard, used as hotkey, so I had to use copy&paste)
* build5 (first external release)
* enhancements: 'Match count only' mode. FU 647: signed integer conversion.
*
*build4
* patch1: lookup table moved from v1420-1451 to v1460-1491, there was a sharing violation
* bugfix1: FU645 part2 check: y3<1 instead of y3<0. If y3=0, part2 010 mask will select bits 0-31, not empty sequence..
** we should have part2 only if lenght2>0, so exit if <1.
--------------------------------------------------------------------------------
TEST SECTION;
* tesztek:
* mode0: ok
* mode1: ok
* mode2: ok
* mode3:
* mode4:
* mode5:
* mode6:
* mode7:
!?CM0;
!!VRv24:Sv1491 :2;
!!IF:M^v1491=%V1491, v1491:2=%V24^;
!!FU:E;
*~!~?*CM0;
*~!~!*VRv24:C32768/2/0/0/0/0; input/output
*~!~!*VRv600:C10/10/10/10; lenght list
*~!~!*VRv313:C24/15/26/4/600/0/0; settings
*~!~!*DO645/1/999/1:P2; test call
*~!~!*IF:M^input/output v24:%V24, v25:%V25, v26:%V26,v27:%V27, v28:%V28, v29:%V29^; should be: 32768,2,1,256,0,0
*~!~!*FU:E;
--------------------------------------------------------------------------------
*[BITWISE PACKER];
; used to copy data between bitfield bits/variables and variable list, and to count matches with mask
; 'read' means: copy from bitfield to variable list, 'write' means: copy from variable list to bitfield
; bitfield: consecutive (next to each other) 'v' variables handled bitwise&continuosly (15 v vars=480 bits, and so on..)
; variable list: consecutive (next to each other) 'v' variables handled as separate 32 bit signed integers
** used special variables (with short names):
* v313 pointer: starting variable of bitfield (v1)
* v314 pointer: starting bit of bitfield (b1)
* v315 pointer: starting variable of variable list(v2)
* v316 value: step counter (total number of executions), MAX. 999 (sc)
* v317 pointer: variable lenght list // value: variable lenght(L)
* v318 value: Shift per turn (S)
* v319 not used, or match counter (nu, MC) HAVE TO RESET MANUALLY.
** x1: mode, including read/write sub-mode
** x2: match counter selection mask
** x3: write enabled(=0)or disabled(<>0) for 'counter only' mode
** v1460-v1491: read only lookup table to compute 2^0..2^31.
* variable lenght list: user defined lenghts for variables on bitfield, max. lenght 31 bit
* variable sequence: whole, consecutive(next to each other) v variables ( for input/output
---
** Usage: ~~DO64'$1'/1/'$2'/1:P'$3'; where '$1'=4,5,6; v316<='$2'<=999; and $3=0/1,2/3,or 4/5 for read/write
** exemple: ~~VRv313:C.. followed by ~~DO 645/1/999/1:P2; means read user defined composite variables
** You can always set '$2' to 999, but You can lower it for security reasons.
** Bitwise packer may overwrite foreign variables, if You mistype v316 counter value.
** Please, double check VR:C settings at least for v313..v317. Thanks.
**
* FU644
* Mode0 read bits from bitfield, and write to variable sequence
* Mode1 read ZERO/NOT ZERO state of variables, and write bitfield bits accordingly (NOT ZERO means 1)
** Compairing to 'bit' macro: Input parameters: bit position <0, or >31 allowed, direct bit write allowed,
** multiple read/write allowed, and much faster execution.. Longer commands, but more features.
** Count matches with mask: 0/not 0.
* FU645
* Mode2 read user defined bit sequences from bitfield, and write to variable sequence
* Mode3 read bit sequences from variable sequence, and write them to bitfield
** Variable lenght list used. ( Match counter not used.)
* FU646
* Mode4 read user defined bit sequences with fixed lenght and shift, and write to variable sequence,
** and count number of matches in v319.
* Mode5 read bit sequences with fixed lenght and shift from variables, and write them to bitfield,
** and count number of matches in v319.
*** So if you start to read from v24 bit15 with lenght 3, shift 45,
*** then sequence lenght will be 3 bit, and next 3 bit sequence will start at v24b15 +45= v25 bit28
* FU647
* Mode6 convert user defined n bit signed integers to 32 bit signed integers, and count number of matches in v319.
* Mode7 convert 32 bit signed integers to user defined n bit signed integers, and count number of matches in v319.
** sign bit will be moved between bit'n-1' and bit31. (Most significant bit handled as sign bit)
** n bit integers have to be stored in separate variables. So copy out from bitfield with FU 645/646,
** and then convert with FU 647. Matches will be counted with 32 bit integer forms.
HINTs;
* FU 644 is intended to read/write 1 bit 'system flags' stored in v variables.
* FU 645 is intended to read/write user defined composite variables with several(different) sub-variables.
** (hypotethical) Exemple 1:
** "Caravan to Town" variable consists of (owner, creature type, quantity, experience, timer, WB flag),
** sub-variable lenghts are, let say: 3,8,10,13,4,1 bits. 39 bits in Total.
* FU 646 is intended to read/write a given sub-variable sequence of user defined composite variables,
** or user defined variable sequence in an index table (variables of the same type).
** (hypotethical) Exemple 1: Arrival times of Caravans for a given Town: subtype timer(lenght=4bit),
** shift= lenght of "Caravan variable" (39 bits, see above),max. 7 Caravans per Town, so (lenght=4, shift=39, counter=7)
** Exemple 2: Number of potions owned by actual hero: max. 7 potion/type, 6 type ->6* 3bit in w variable.
** First you have to copy out the w variable to a v variable, then everything as usual. (lenght=3,shift=3, counter=6)
** Exemple 3: Lookup table for 'Caravans': max. 7 caravans per target Town, actual number stored in a 48*3bit table.
** /max. 48 Towns per map, 3 bit to store 0..7 values, so a 144 bit long bitfield needed/(lenght=3,shift=3,counter=48)
--------------------------------------------------------------------------------
BITWISE PACKER SETUP; lookup table to calculate 2^x (x:0-31) placed on v1460-v1491 for speedup
!#VRv1460:C1/2/4/8/16/32/64/128/256/512/1024/2048/4096/8192/16384/32768;
!#VRv1476:C65536/131072/262144/524288/1048576/2097152/4194304/8388608/16777216/33554432/67108864/134217728/268435456/536870912/1073741824/-2147483648;
** v1491= +2147483648 also tested ok, but -2147483648 is used ..
--------------------------------------------------------------------------------
* y1..y10: "more important" values, y90-100:temporary
* counter(Last Turn?) checks: "<=" instead of "=" for safety reasons
*FU 644;
* v313 pointer: starting variable of bitfield (v1)
* v314 pointer: starting bit of bitfield (b1)
* v315 pointer: starting variable of variable list(v2)
* v316 value: step counter (total number of executions), MAX. 999 (sc)
* v317 not used (lenght always 1)
* v318 value: Shift per turn (S)
* v319 not used, or match counter (nu, MC) HAVE TO RESET MANUALLY.
** x1: mode, including read/write sub-mode
** x2: match counter selection mask (0 or not 0, if used) /0 by default/ (SM)
** x3: write enabled(=0)/disabled(<>0) for 'match count only' mode, enabled by default (WE)
** Match Counter is always ON.
MODE0;
; copy bit values from bitfield var1 bit1 to variable sequence starting with vv317, until x16<step counter
; setup v313-v319 with VR:C and then ~~DO644/1/999/1:P0;
MODE1;
;write bits to bitfield, if v2 not 0, until x16<step counter
; setup v313-v319 with VR:C and then ~~DO644/1/999/1:P1;
!?FU644;
; offset handling: actual v1,b1
!!VRy90:Sv314 :32; dv1
!!VRv314:%32;b1
!!VRv313:Sdy90;v1
* y90 free
; create selection mask for var v1 bit b1
!!VRy90:S1460 +v314;
!!VRy1:Svy90;
!!VRy2:S-1 -y1; inverted mask
; select b1
!!VRy3:Svv313 &y1;
!!VRy3&y3<>0:S1;
; read
!!VRvv315&x1=0/x3=0:Sy3;
; write
!!VRy1&vv315=0:S0; check if zero
!!VRvv313&x1=1/x3=0:&y2 |y1; reset b1 bit, and set if vv315 not zero
; increment pointers for next turn
!!VRv314:Sdv318;b1
!!VRv315:Sd1; v2
; check counter
!!VRx16&v316<=x16:S999; Is it last turn?
; Match count (0, or not 0)
!!VRy91&x2<>0:S1; selection mask
!!VRy92&vv315<>0:S1; v2 is 0, or not 0?
!!VRv319&y3=y91/x1=0:Sd1; count if read
!!VRv319&y92=y91/x1=1:Sd1; count if write
--------------------------------------------------------------------------------
*FU 645
* v313 pointer: starting variable of bitfield (v1)
* v314 pointer: starting bit of bitfield (b1)
* v315 pointer: starting variable of variable list(v2)
* v316 value: step counter (total number of executions), MAX. 999 (sc)
* v317 pointer: variable lenght(L) list
* v318 not used
* v319 not used
** x1: mode, including read/write sub-mode
** Remark: This FU is used to copy a set of different variables, so Match counter makes no sense.
MODE2;
; read bit sequence FROM variable vv313 bit v314, lenght vv317, and write output TO vv315,
*until x16< v316 step counter. /v# -> vv# pointers will be shifted for next round/
; setup v313-v319 with VR:C and then ~~DO645/1/999/1:P2;
!?FU645;
!!FU&x1<>2:E;
; offset handling: actual v1,b1
!!VRy90:Sv314 :32; dv1
!!VRv314:%32;b1
!!VRv313:Sdy90;v1
* y90 free
; copy source values
!!VRy1:Svv313; v1
!!VRy2:Svv317; L
; actual bit sequence is in one, or two variables?
!!VRy3:Sv314 +y2 -32; calculate next var starting bit=lenght2 if two parts
!!VRy2&y3>0:-y3; L1
; first step: down to bit0
!!VRy90:S1460 +v314; lookup 2^b1
!!VRy4:Svy90;
*y90 free
*down to bit0* there are no unsigned 32 integers in WoG; going around the problem..
!!VRy5:Sy1 &2147483647 :y4; select bit0-30. bit31 not shifted now(-10:32=0, instead of 67108864..shifted bit31 missing)
!!VRy90:S2147483648 :y4; select bit31. playing with signed 32 integer abilities. 2^31 handled as -2^31, not -0
)
* remarks: y90<0, so if y1<1, all bits above shifted bit31 will become 1, but later we have a selection mask.
!!VRy5&y1<0:|y90; copy parts together. Now shifting is ok.
*y90 free
; selection mask for bit sequence, calculate 2^L1-1
!!VRy90:S1460 +y2;
!!VRy6:Svy90; needed for part2
!!VRy7:Sy6 -1; mask
!!VRvv315:Sy5 &y7; OUTPUT PART1
* y1,2,4,5,7,90 free
;increment pointers for next turn
!!VRv314:Sdy2; b1+L1
!!VRv315&y3<1:Sd1; v2 pointer* "not >0" equals with "<1" (y3 is integer)
!!VRv317:Sd1; L pointer
; counter
!!VRx16&v316<=x16:S999; Is it last turn?
!!FU&y3<1:E;
** PART2
; lenght2 in y3, v1= v313 +1, output2 offset in y6, v315 actual
!!VRy90:Sv313 +1; v1+1 pointer
; select sequence part2, calculate 2^L2-1
!!VRy91:S1460 +y3;
!!VRy92:Svy91 -1; mask
!!VRy4:Svy90 &y92 *y6; OUTPUT PART2 (shifted up)
!!VRvv315:|y4; OUTPUT
;increment pointers for next turn
!!VRv314:Sdy3; b1+L2
!!VRv315:Sd1; v2 pointer*
MODE3;
; write bit sequence TO variable vv313 bit v314, lenght vv317, FROM vv315, until x16< v316 step counter
* /v# -> vv# pointers will be shifted for next round/
; setup v313-v319 with VR:C and then ~~DO645/1/999/1:P3;
** Variable boundary inside bit sequence enabled,
** for exemple: sequence from v600 bit 24 to v601 bit 7: v313 600, v314 (b1) 24, Lenght vv317=16
** Max. allowed sequence lenght is 31 bit, so source bit31 shift not needed.
!?FU645;
!!FU&x1<>3:E;
; offset handling: actual v1,b1
!!VRy90:Sv314 :32; dv1
!!VRv314:%32;b1
!!VRv313:Sdy90;v1
* y90 free
; copy source&target values
**VRy1:Svv313; v1 not needed
!!VRy2:Svv317; L
!!VRy1:Sy2; copy for inc
!!VRy4:Svv315; v2
; sequence will be in one, or two variables?
!!VRy3:Sv314 +y2 -32; calculate next var starting bit=lenght2 if two parts L2
!!VRy2&y3>0:-y3; L1
; preparations for part1
* calculate 2^L1-1 for 0x0 selection mask, *2^v314 to shift in position
!!VRy90:S1460 +y2;
!!VRy5:Svy90; needed for part2 for source shifting
!!VRy6:Sy5 -1; 0x0 mask 2^L1-1
!!VRy7:S1460 +v314; shift
*y90 free
; write part1:
* create 101 mask to target region reset, OR it with shifted source
* remarks: yyy AND 101= y0y, OR 0x0 = yxy, where yyy target, xxx source, selected region to write: 0x0.
!!VRy8:Sy4 &y6 *y7; shifted source 0x0
!!VRy90:Sy6 *y7; shifted 010 mask
!!VRy9:S-1 -y90; 101 mask
*y90 free
!!VRvv313:&y9 |y8; part1 OUTPUT
;increment pointers for next turn
!!VRv314:Sdy1; b1+L * not used in part2
!!VRv315:Sd1; v2 pointer *not used in part2
!!VRv317:Sd1; L pointer
; counter
!!VRx16&v316<=x16:S999; Is it last turn?
!!FU&y3<1:E; exit if only one part
** y1-y2,y6-y9 free; source in y4, y3 lenght2, y5 2^L1
** PART2
; preparations for part2
!!VRy90:S1460 +y3; 2^L2
!!VRy1:Svy90 -1; 010 mask
!!VRy2:S-1 -y1; 101 mask
!!VRy6:Sv313 +1; target2 pointer
; write part2
* Down to bit0 with source2, selection mask, reset target2, OR with source2
!!VRy4::y5 &y1; down to bit0 & select
!!VRvy6:&y2 |y4; reset target2, OR with selected source part; part2 OUTPUT
--------------------------------------------------------------------------------
*FU 646
* v313 pointer: starting variable of bitfield (v1)
* v314 pointer: starting bit of bitfield (b1)
* v315 pointer: starting variable of variable list(v2)
* v316 value: step counter (total number of executions), MAX. 999 (sc)
* v317 value: variable lenght(L)
* v318 value: Shift per turn (S)
* v319 match counter (MC) HAVE TO RESET MANUALLY.
** x1: mode, including read/write sub-mode
** x2: match counter selection mask
** x3: write enabled(=0)or disabled(<>0) for 'counter only' mode (WE)
** Match Counter is always ON.
MODE4; biggest part copied out from mode 2, changes marked with ***
; read bit sequence FROM variable vv313 bit v314, lenght v317, and write output TO vv315,
*until x16< v316 step counter. /v# -> vv# pointers will be shifted for next round/
; setup v313-v319 with VR:C and then ~~DO646/1/999/1:P4/SM/WE;
!?FU646;
!!FU&x1<>4:E; ***
; offset handling: actual v1,b1
!!VRy90:Sv314 :32; dv1
!!VRv314:%32;b1
!!VRv313:Sdy90;v1
* y90 free
; copy source values
!!VRy1:Svv313; v1
!!VRy2:Sv317; L *** Am I lazy?
; actual bit sequence is in one, or two variables?
!!VRy3:Sv314 +y2 -32; calculate next var starting bit=lenght2 if two parts
!!VRy2&y3>0:-y3; L1
; first step: down to bit0
!!VRy90:S1460 +v314; lookup 2^b1
!!VRy4:Svy90;
*y90 free
*down to bit0* there are no unsigned 32 integers in WoG; going around the problem..
!!VRy5:Sy1 &2147483647 :y4; select bit0-30. bit31 not shifted now(-10:32=0, instead of 67108864..shifted bit31 missing)
!!VRy90:S2147483648 :y4; select bit31. playing with signed 32 integer abilities. 2^31 handled as -2^31, not -0
)
* remarks: y90<0, so if y1<1, all bits above shifted bit31 will become 1, but later we have a selection mask.
!!VRy5&y1<0:|y90; copy parts together. Now shifting is ok.
*y90 free
; selection mask for bit sequence, calculate 2^L1-1
!!VRy90:S1460 +y2;
!!VRy6:Svy90; needed for part2
!!VRy7:Sy6 -1; mask
!!VRy8:Sy5 &y7; *** speeding up match count, OP1 temp value
!!VRvv315&x3=0:Sy8; OUTPUT PART1 *** write enabled?
* y1,2,4,5,7,90 free
;increment pointers for next turn
*** NO v314 shift with L1
!!VRv314:Sdv318; because shift value is set manually (v314 not used in part2)
!!VRv315&y3<1:Sd1; v2 pointer* "not >0" equals with "<1" (y3 is integer)
*** NO v317 shift
; Match Count, PART1 ***
!!VRv319&y8=x2/y3<1:Sd1;
; step counter
!!VRx16&v316<=x16:S999; Is it last turn?
!!FU&y3<1:E;
** PART2
; lenght2 in y3, v1= v313 +1, output2 offset in y6, v315 actual, output1 in y8
!!VRy90:Sv313 +1; v1+1 pointer
; select sequence part2, calculate 2^L2-1
!!VRy91:S1460 +y3;
!!VRy92:Svy91 -1; mask
!!VRy4:Svy90 &y92 *y6; Output Part2 (shifted up)
!!VRy9:Sy8 |y4; *** speeding up match count, final OP temp value
!!VRvv315&x3=0:Sy9; OUTPUT *** write enabled?
;increment pointers for next turn
*** NO v314 shift with L2
!!VRv315:Sd1; v2 pointer*
; Match Count, PART2 ***
!!VRv319&y9=x2:Sd1;
MODE5; biggest part copied out from Mode3, changes marked with ***
; write bit sequence TO variable vv313 bit v314, lenght v317, FROM vv315, until x16< v316 step counter
* /v# -> vv# pointers will be shifted for next round/
; setup v313-v319 with VR:C and then ~~DO646/1/999/1:P5;
** Variable boundary inside bit sequence enabled,
** for exemple: sequence from v600 bit 24 to v601 bit 7: v313=600, v314 (b1) 24, Lenght v317=16
** Max. allowed sequence lenght is 31 bit, so source bit31 shift not needed.
!?FU646;
!!FU&x1<>5:E; ***
; Match count *** ->
!!VRv319&vv315=x2:Sd1;
!!VRv315&x3<>0:Sd1;
!!FU&x3<>0:E; -> *** exit if write disabled
; offset handling: actual v1,b1
!!VRy90:Sv314 :32; dv1
!!VRv314:%32;b1
!!VRv313:Sdy90;v1
* y90 free
; copy source&target values
**VRy1:Svv313; v1 not needed
!!VRy2:Sv317; L ***
** copy y2 to y1 for inc ***
!!VRy4:Svv315; v2
; sequence will be in one, or two variables?
!!VRy3:Sv314 +y2 -32; calculate next var starting bit=lenght2 if two parts L2
!!VRy2&y3>0:-y3; L1
; preparations for part1
* calculate 2^L1-1 for 0x0 selection mask, *2^v314 to shift in position
!!VRy90:S1460 +y2;
!!VRy5:Svy90; needed for part2 for source shifting
!!VRy6:Sy5 -1; 0x0 mask 2^L1-1
!!VRy7:S1460 +v314; shift
*y90 free
; write part1:
* create 101 mask to target region reset, OR it with shifted source
* remarks: yyy AND 101= y0y, OR 0x0 = yxy, where yyy target, xxx source, selected region to write: 0x0.
!!VRy8:Sy4 &y6 *y7; shifted source 0x0
!!VRy90:Sy6 *y7; shifted 010 mask
!!VRy9:S-1 -y90; 101 mask
*y90 free
!!VRvv313:&y9 |y8; part1 OUTPUT
;increment pointers for next turn
!!VRv314:Sdv317; b1+v317 as shift value instead of y1=L * not used in part2 ***
!!VRv315:Sd1; v2 pointer *not used in part2
** L not in pointer ***
; counter
!!VRx16&v316<=x16:S999; Is it last turn?
!!FU&y3<1:E; exit if only one part
** y1-y2,y6-y9 free; source in y4, y3 lenght2, y5 2^L1
** PART2
; preparations for part2
!!VRy90:S1460 +y3; 2^L2
!!VRy1:Svy90 -1; 010 mask
!!VRy2:S-1 -y1; 101 mask
!!VRy6:Sv313 +1; target2 pointer
; write part2
* Down to bit0 with source2, selection mask, reset target2, OR with source2
!!VRy4::y5 &y1; down to bit0 & select
!!VRvy6:&y2 |y4; reset target2, OR with selected source part; part2 OUTPUT
--------------------------------------------------------------------------------
*FU 647: Conversion between n-bit and 32bit signed values.
; bit0-(n-2) copied, moving bit(n-1) <->bit31. Read: ->, write: <-
* v313 not used
* v314 not used
* v315 pointer: starting variable of variable list(v2)
* v316 value: step counter (total number of executions), MAX. 999 (sc)
* v317 value: variable lenght(L), 1-31
* v318 value: Shift per turn (S) FOR v2, counted in 32 bit variables
* v319 match counter (MC) HAVE TO RESET MANUALLY.
** x1: mode, including read/write sub-mode
** x2: match counter selection mask
** x3: write enabled(=0)or disabled(<>0) for 'counter only' mode (WE)
** Match Counter is always ON.
* Please, don't forget to set and check v318.
MODE6; convert n bit signed integers to 32 bit signed integers.
!!FU&x1<>6:E;
; convert
!!VRy1:Svv315; read in
!!VRy90:S1460 +v317;
!!VRy91:Svy90 -1; select range
!!VRy90:-1;
!!VRy92:Svy90;select sign bit
!!VRy93:S-1 -y92; inverted mask for sign
!!VRy2:Sy1 &y92; sign bit
!!VRy1:&y93; reset sign bit
!!VRy1&y2<>0:|-2147483648; set new sign bit
!!VRvv315&x3=0:Sy1; write if enabled
; Match count
!!VRv319&y1=x2:Sd1;
; Increment pointers
!!VRv315:Sdv318;
; step counter
!!VRx16&v316<=x16:S999; Is it last turn?
MODE7; convert 32 bit signed integers to n bit signed integers. Changes to Mode6 marked with ***
!!FU&x1<>7:E; ***
; copy actual variable
!!VRy1:Svv315; read
; Match count *** ->
!!VRv319&y1=x2:Sd1;
!!VRv315&x3<>0:Sdv318;
; step counter
!!VRx16&v316<=x16:S999; Is it last turn?
!!FU&x3<>0:E; exit, if write disabled -> ***
; convert
!!VRy90:S1460 +v317;
!!VRy91:Svy90 -1; select range
!!VRy90:-1;
!!VRy92:Svy90;select sign bit
!!VRy93:S-1 -y92; inverted mask for sign
!!VRy2:Sy1 &-2147483648; sign bit *** ->
!!VRy1:&y91 &y93; select range,(thus reset bit31,v317<=31), reset new sign bit
!!VRy1&y2<>0:|y92;set new sign bit
!!VRvv315:Sy1; write -> ***
; Increment pointers
!!VRv315:Sdv318;
* END of Bitwise Packer *
--------------------------------------------------------------------------------