3 ; Release Date : february 2001
4 ; Filename : wormy.86p (5kb)
6 ; Email Address : shiar0@hotmail.com
8 ; Web Page : www.shiar.org
9 ; Description : ruling Nibbles-like game 1-4 players
10 ; Where to get this game : www.shiar.org (home of Wormy)
11 ; Other games by author(s) : Nemesis beta
12 ; Additional Credits to : Matthew Shepcar (wrote original Peaworm, end'98)
13 ; Jonah Cohen (helped writing worm)
15 ;-----------------------------
16 ;----------- TO-DO -----------
17 ;-----------------------------
21 ; * implement circle-routine!
22 ; 1% * customizable keys
24 ; * check levels/gametype
25 ; * enough hiscore saves!
27 ; 1% * misc (pollish, bugs, &&&)
29 ; 2% * fix deaths linkplay and transmit game/level data
30 ; 2% * make linkplay available for all gametypes (not just deathmatch)
32 ; 1% * fix pea XOR problem in ctf (+dom?)
34 ; 1% * domination?: take control points by running over them and hold them
36 ;100% = bugs fixed + levels done
38 ;-----------------------------
39 ;-----------------------------
40 ;--------- W O R M ---------
41 ;-----------------------------
42 ;-----------------------------
44 #define buffer ;use display buffer (otherwise write directly to screen)
45 #define readymask ;"grays" out the field before starting a level
47 ;#define readytext ;displays "prepare" before level starts
48 ;#define invincible ;worms cannot die =)
55 #include "ti86asm.inc"
59 _divHLby10 = $4044 ;hl=hl/10
60 _divAby10 = $4DAF ;a=a/10
61 _HLTIMES10 = $41BF ;hl=hl*10
63 _clrWindow = $4A86 ;clear screen
64 _asapvar = $D6FC ;own name (worm)
65 _MOV4B = $429B ;4x ld (de),(hl)
66 _MOV5B = $4297 ;5x ld (de),(hl)
67 _mov9b = $4283 ;9x ld (de),(hl)
68 _ldHLind = $4010 ;ld hl,(hl)
69 _swapt_ = $45F3 ;ex_ahl_bde
70 _Get_Word_ahl = $521D ;ld de,(ahl)
71 _Set_Word_ahl = $5221 ;ld (ahl),de
72 _INC_PTR_AHL = $4637 ;ahl=ahl+1
73 _AHL_PLUS_2_PG3 = $4C3F ;ahl=ahl+2
74 _SET_ABS_SRC_ADDR = $4647 ;set source for mm.ldir =ahl
75 _LOAD_ABS_SRC_ADDR = $5209 ;ahl = mm.ldir source
76 _SET_ABS_DEST_ADDR = $5285 ;set destination for mm.ldir = ahl
77 _SET_MM_NUM_BYTES = $464F ;number of bytes for mm.ldir = ahl
78 _mm_ldir = $52ED ;24bit ldir
79 _RAM_PAGE_1 = $47E3 ;set $8000+ to page 1
81 _PTEMP_END = $D29A ;end of VAT
82 _load_ram_ahl = $462F ;ahl->page+hl
83 _writeb_inc_ahl = $5567 ;ld (ahl),c
84 _jforce = $409C ;TI-OS stack restored
85 _EXLP = $4493 ;swap (hl),(de) b times
87 ;-----------------------------
88 ;------- data storage -------
89 ;-----------------------------
93 ScrBuffer = $8820 ;-A7FF (20*FF=1FE0)
94 worm2p = $A800 ;-ABFF (400) %10101O00
95 worm1 = $AC00 ;-AC1D (31d)
96 worm2 = $AC1F ;-AC3B (1F)
97 worm3 = $AC3E ;-AC59 (1F)
98 worm4 = $AC5D ;-AC77 (1F)
99 balls = $AC7C ;-ACFF (3x43d)
100 SinCosTable = $AD00 ;-AE00 (4x40)
101 ;free $AE01 ;-AFFF (1FF)
102 worm1p = $B000 ;-B7FF (800) %1011O000
103 worm3p = $B800 ;-BBFF (400) %10111O00
104 ;free $BF91 ;-BFFF (6F)
106 ;program $D748 ;-E7FF (106D+4A)
107 ;free $E800 ;-EFFF (800)
108 worm4p = $F000 ;-F3FF (400) %11110O00
109 leveldata = $F400 ;-FA70 (<=671)
115 namelength = $BC00 ;(1) @menu
117 DispBuffer = $BC00 ;(10x57d) @game
122 ;-----------------------------
123 ;------- program start -------
124 ;-----------------------------
139 .db "WORMY by SHIAR -- alpha 92.5%",0
142 .db %10010110,%01101111
143 .db %10110101,%01001011
144 .db %01110011,%01001001
145 .db %00000011,%10000000
146 .db %00000001,%11100000
147 .db %00111000,%11111000
148 .db %01111110,%00111111
149 .db %11101111,%00001111
150 .db %11000011,%10000000
153 levelhead2 = 92 ;wormy levels header = "92"
184 ld bc,int_end-int_handler
191 ld hl,$BFFF ;VAT start
194 ld de,(_PTEMP_END+1) ;VAT end
227 ex de,hl ;ld ahl,(hl)
228 cal _AHL_PLUS_2_PG3 ;string id
229 cal _Get_Word_ahl ;ld de,(ahl)
234 jr nz,searchnext ;not worm
252 cal _Get_Word_ahl ;ld de,(ahl++)
257 ld a,e ;set new level
282 cal _puts ;"< Select levels: >"
301 cal _load_ram_ahl ;hl=ahl
302 ld b,(hl) ;b=title size
304 cal _putps ;destr=abchl
322 cp K_ENTER-K_EXIT+256
327 or a ;levelfile on page 0 (=internal)
337 ld (leveldataSize),de
346 cal _SET_ABS_SRC_ADDR ;levelsstart
349 cal _SET_ABS_DEST_ADDR ;store in mem.
352 cal _SET_MM_NUM_BYTES
355 cal _LOAD_ABS_SRC_ADDR ;->ahl
362 ldi ;(de),(hl)\inc hl
367 res 2,(iy+13) ;appAutoScroll
371 ;-----------------------------
372 ;----- build trig tables -----
373 ;-----------------------------
398 ;-----------------------------
399 ;---------- menu -------------
400 ;-----------------------------
402 DisplayMenu: ;---draw menu---
426 cal _vputs ;by Shiar \ Mode \ Level \ Limit \ Worms
430 jr setgame ;> dispmenusets > mainMenu
442 jp LetsGetThisPartyOn ;1/3/4
468 jr c,mainMenu ;type 0/1
473 jr nc,mainMenu ;may not be >4
476 jr dispmenusets ;mainMenu
488 ; jr z,bchangenrworms
494 jr nz,changednrworms ;save >0
507 ld (curlevel),a ;reset level#
508 ld hl,nrworms ;reset #worms
512 jr c,dispmenusets ;<2=singleplayer
514 jr dispmenusets ;mainMenu
527 jr dispmenusets ;mainMenu
534 cal loadgamecar ;c=(gameCar)
535 ;a=(hl)=(Gametype+1)=(wormbeglives)
540 pop hl ;restore stack
541 jr _mainMenu ;singleplayer (no limit)
549 ld d,(hl) ;max level for sel.game
557 jr dispmenusets ;mainMenu
565 ;---display current settings---
588 add hl,de ;hl=posGame+(Gametype)
589 ld a,(hl) ;str.offset
593 ld (CURtxtGame),hl ;save for g/o
594 cal _vputs ;Singleplayer
610 cal cshowA ;liveslimit
622 ;--- handle menukeys ---
631 pop bc ;GET_KEY destr. b
641 menupos: ;highlight #b
654 add hl,hl ;$FD20+item*96
684 cal _puts ;"Enter name player "
773 .db 0,".<>!",0,0,0,0 ;down,L,R,up
774 .db 0,"XTOJE0",0 ;enter..clear
775 .db " WSNID9",0 ;(-)..custom
776 .db "ZVRMHC8",0 ;dot..del
777 .db "YUQLGB7#" ;0..xvar
778 .db $D9,"-PKFA6'" ;on..alpha
779 .db "54321*",0,$D0 ;F5..more
783 skiplevel: ;@hl - destr:ab - alter:hl
788 ld b,(hl) ;spritesize
799 inc b ;multiplayer lvl
801 inc b ;skip other 3 worms (9 bytes)
835 ;build: c=(gameCar)=(hl-1)
836 ; a=(wormbeglives)=(hl)
852 ;-----------------------------
853 ;-------- start game ---------
854 ;-----------------------------
858 ld (CheckExit),a ;set exit state
863 cal _HLTIMES10 ;hl=10*(hl)
864 ld (scorelimit),hl ;set limit
868 sbc hl,de ;datalevels
879 dec a ;ld a,$FF ;=no_limit
883 cal _ldHLind ;ld hl,(hl)
888 dec d ;levels to skip
932 ;-----------------------------
933 ;--------- game over ---------
934 ;-----------------------------
940 ld a,4 ;4x (all worms)
956 ex de,hl ;de=wormX+head
960 jr nz,createwormsloop
962 pop hl ;begin of current level
974 ;show end msg or smtn
976 psh bc ;where to go afterwards
977 inc hl ;location of ending-code
978 jp (hl) ;go there ("call")
1000 ld b,0 ;bc=sprite size
1001 add hl,bc ;hl=behind sprite
1008 setsprite: ;de=@sprite ;a=sprsize
1041 ld a,SinCosTable/256
1053 ld bc,(worm2-worm1)-5
1058 ;-------- draw level ---------
1144 ;-----------------------------
1146 psh hl ; >> levelp new
1181 ld hl,4+(txtposReady*256)
1192 jr z,initfinished ;no link
1195 ld (worm2+input),a ;worm 2 via link
1197 ld (Speed),a ;max.speed
1198 SwapPos: ;$18 xx -> $F6 xx
1202 ld (worm2+left),a ;1
1205 ld b,4 ;+heading +pos
1206 cal _EXLP ;swap positions
1211 cal _EXLP ;swap positions
1220 ;-----------------------------
1221 ;----------- LOOP ------------
1222 ;-----------------------------
1241 jr nz,screeninvertloop
1257 cal nz,handlethoseneatlittleballs
1270 ;-----------------------------
1271 ;---------- keys -------------
1272 ;-----------------------------
1287 rla ;=$17 (c=EXIT-key)
1298 ld (ix+delay),respawndelay
1317 ret nz ;HandleWorm done
1321 ld a,$A7 ;exit@end of turn
1322 ld (CheckExit),a ;set exit state
1358 cp (hl) ;input=0 = link
1383 ld a,(hl) ;worm+died
1391 cal _ldHLind ;ld hl,(hl)
1392 cal showHL ;worm+score
1398 dnz displayWormStats
1401 or a ;singleplayer (0) only
1402 jr nz,hilevelcheckdone
1407 jr c,hilevelcheckdone
1408 ld (hl),a ;save local
1413 hilvlposhl =$-2 ;save external
1414 cal _writeb_inc_ahl ;ld (ahl),c
1420 jr z,hiscorecheckdone
1422 cal loadhiscoreposinahl
1423 cal _Get_Word_ahl ;de=old_hi
1431 jr c,NotNewHigh ;New<Old
1432 jr nz,newhigh ;New>Old
1436 jr nc,NotNewHigh ;new<old
1440 cal loadhiscoreposinahl
1441 cal _Set_Word_ahl ;de->(ahl)
1444 NotNewHigh: ;de=current hiscore
1465 ;x123456789012345678901
1466 ;1----- GAME OVER -----
1471 ;6Worm#02 @ 05 00120
1477 rst 20h ;_ABS_MOV10TOOP1
1479 ld hl,savestart-_asm_exec_ram+4
1483 cal _SET_ABS_DEST_ADDR
1487 cal _SET_ABS_SRC_ADDR
1488 ld hl,saveend-savestart
1489 cal _SET_MM_NUM_BYTES
1498 loadhiscoreposinahl:
1503 ld a,(nrlevels+1) ;# peaworm lvls
1510 dec a ;z=(Gametype)=2
1522 hiscrposa =$-1 ;ahl=saveloc
1528 dnz addlevelposition
1531 ;-----------------------------
1532 ;----------- worm ------------
1533 ;-----------------------------
1538 cal saverespawncounter
1544 jr DoesWormTailEqualsWormHead ;chk4 size=0
1555 DoesWormTailEqualsWormHead:
1557 jr nz,removewormloop
1561 jr nz,safewormsizedone
1569 ld (ix+tail),e ;head=tail/size=0
1575 jr nz,saverespawncounter
1593 inkeys: ;use jp not call!
1640 ;------- handle worm ---------
1679 ;-------- move worm ----------
1707 notmoveY: ;bc=newpos
1714 pop hl ; << pos (old)
1732 ;--------- worm hit ----------
1738 cal z,checkhitotherworm
1740 and _datamultpeas ;&&bit
1744 jp z,WormDead ;no food
1751 cal DrawPea ;remove pea
1763 jp nz,Drawworm ;continue
1769 jp nz,Exit ;stack restored
1780 cal IncScore ;score+(40*level)
1784 pop hl ; << levelp new
1788 chkpeahit: ;hl=peapos
1817 ld hl,(peaspos) ;1st pea
1823 ld hl,(peaspos+2) ;2nd pea
1826 pop hl ;(peapos) 1st pea
1827 jp c,stopworm ;own pea hit
1829 ld a,e ;peek a (that x86 asm for pop\push ;)
1832 ld hl,(peaspos+2) ;2nd pea
1845 cal DrawPea ;restore own flag
1846 jr sillylabel ;inv both\die
1848 hitflag: ;correct pea hit
1866 ret ;Z=yes: no flag taken
1868 ;-----------------------------
1887 jr nz,nextotherwormbit
1912 .db $dd,$7d ;ld a,lx
1915 jr nz,chkworm2 ; ret nz
1940 ;-------- draw worm ----------
1949 cal z,checkhitlapline
1955 ret z ;keep tail in "Tron"
1998 ;-----------------------------
1999 ;---------- ball -------------
2000 ;-----------------------------
2002 handlethoseneatlittleballs:
2048 bit 1,d ;1=up; 0=down
2078 letsmovetheotherway:
2093 ;-----------------------------
2094 ;----------- procs -----------
2095 ;-----------------------------
2099 ld a,%10000000 ;all key-masks
2102 inc a ;cp %11111111 (no keys pressed)
2103 jr nz,releasekeys ;keep waitin
2104 cal GET_KEY ;clear buffer
2150 jr nz,NewPea ;pixel found
2157 ;all ok; empty space
2166 ;----------- score -----------
2186 jr z,scorecommon ;hl/1000 not increased
2194 jr c,showstats ;<0=0
2201 jr z,showstats ;de=$FF??=no limit
2342 ;-----------------------------
2460 ld (ShiftRightCounter),a
2462 ld (ShiftRightChunk),a
2476 ShiftRightCounter = $-1
2498 ld (ShiftLeftCounter),a
2500 ld (ShiftLeftChunk),a
2502 jr nc,ShiftLeftSameByte
2521 ShiftLeftCounter = $-1
2532 jr nz,ShiftRowsRight
2566 ;----------- draw ------------
2580 CheckPixel: ;at bc in d
2587 ;CLEM's FIND_PIXEL (131+? cycles; 28+4 bytes)
2588 ;(b,c) to hl:a; "destroyes" ahl
2590 FindPixel: ;(b,c) to hl:a
2623 PutSprite: ;||@(b,c)
2624 ;by SHIAR only ix saved
2691 drawbox: ;(d,e)-(h,l)
2817 ;-----------------------------
2818 ;----------- link ------------
2819 ;-----------------------------
2849 Csend: ;--- send 8 bits in A --- destr:abcdehl ---
2855 out (7),a ;both high
2856 jr Csendloop ;CF = error
2858 Qsend: ;--- try to send 8 bits in C; CF=error --- destr:abcdehl ---
2864 ld b,8 ;bits to send
2867 rl c ;bit to send in cf
2868 ld a,D0LD1H ;0: lower white
2870 ld a,D0HD1L ;1: lower red
2872 out (7),a ;lower one (send bit)
2874 cal checklink ;other calc must lower other wire
2876 ld a,D0HD1H ;raise one, ok to raise other
2880 cp %11 ;both raised (by other calc)
2883 dnz sendloop ;repeat for all bits
2891 Crecv: ;--- receive 8 bits into A/C --- destr:abcdehl ---
2893 ret nc ;return if all went ok
2895 out (7),a ;raise both on error
2896 jr Crecv ;and try again
2898 Qrecv: ;--- receive 8 bits into A/C; CF=error --- destr:abcdehl ---
2901 jp z,Exit ;both low = error, quit
2904 ret z ;both high = nothing yet, wait
2905 ld b,8 ;bits to receive
2911 jr z,recvwait ;both high = nothing sent (yet)
2912 rra ;received bit in cf
2914 jr c,received ;lower white wire as well
2915 ld a,D0HD1L ;lower red
2918 out (7),a ;both wires low
2921 jr z,recvwaitack ;same wire will be raised again by other calc
2923 out (7),a ;raise both
2925 dnz recvloop ;repeat for all bits
2930 ;-----------------------------
2931 ;---------- levels -----------
2932 ;-----------------------------
2935 .db 5,4,15,15,0,0 ;peas,speed,growth,begin_size,sprite,balls
2936 .db 0,2,63 ;start d, y, x
2937 .db 128,57 ;field width (128-255), height (57-255)
2938 .db 0 ;no additional lines, boxes
2945 .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
2950 .db %1110000,%10001000,%10001000,%10001000,%1110000,0
2951 .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
2957 .db %1110000,%10001000,%10001000,%10001000,%1110000,0
2958 .db $40,30,64,$C0,30,64, $00,30,64,$80,30,64
2962 ;-----------------------------
2963 ;---------- data -------------
2964 ;-----------------------------
2967 .db %00011110,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000
2968 .db %00111110,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000
2969 .db %01110000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000
2970 .db %01100000,%01111100,%00000001,%11111111,%00000000,%11110000,%01111001,%11100000
2971 .db %11100000,%11111110,%00000011,%11111111,%10000011,%11111000,%11111111,%11110000
2972 .db %11000001,%11000111,%00000111,%00000001,%11000111,%10011001,%11001111,%00111000
2973 .db %11000001,%10000011,%00000110,%00000000,%11100110,%00000001,%10011111,%10011000
2974 .db %11000001,%10000011,%00000110,%11000000,%01101110,%00000011,%10111001,%11011100
2975 .db %11000001,%11000111,%00000110,%11000000,%01101100,%00000011,%00110000,%11001100
2976 .db %11000000,%11000110,%00000110,%11000000,%01101100,%00000011,%00110000,%11001100
2977 .db %11100000,%11101110,%00001110,%11000000,%01101100,%00000011,%00111001,%11001100
2978 .db %01100000,%01111100,%00001100,%11000000,%01101100,%00000011,%00011111,%10001100
2979 .db %01110000,%00111000,%00011100,%11100000,%11101110,%00000011,%00001111,%00001100
2980 .db %00111000,%11111110,%00111000,%01110001,%11000110,%00000011,%10000000,%00011100
2981 .db %00011111,%11101111,%11110000,%00111111,%10000111,%00000001,%10000000,%00011000
2982 .db %00001111,%10000011,%11100000,%00011111,%00000011,%00000001,%10000000,%00011000
2984 txtMenu: .db "by Shiar",0
2986 .db "Level",0 ;4th menu item
2989 posMenu: .dw $0D5A,$1418,$131E,$1524,$0F2A
2990 txtGame: .db "Singleplayer",0 ;0 (1st)
2991 txtGame1: .db "Peaworm",0 ;1 (next 1st)
2992 txtGame2: .db "Tron",0 ;2
2993 txtGame3: .db "Deathmatch",0 ;3
2994 txtGame4: .db "Foodmatch",0 ;4
2995 txtGame5: .db "LinkMatch",0 ;5
2996 txtGame6: .db "Race",0 ;6
2997 txtGame7: .db "CTF",0 ;7
2998 ; .db "Domination",0 ;8
2999 posGame: .db 0,txtGame1-txtGame
3000 .db txtGame2-txtGame
3001 .db txtGame3-txtGame
3002 .db txtGame4-txtGame
3003 .db txtGame5-txtGame
3004 .db txtGame6-txtGame
3005 .db txtGame7-txtGame
3007 txtLevsel: .db $CF," Select levels: ",5,0
3008 txtName: .db "Enter name player ",0
3009 txtWaiting: .db "Waiting...",0
3010 txtReceive: .db "Receiving..." ;,0
3013 .db 0, 3, 6, 9, 12, 15, 18, 21
3014 .db 24, 27, 30, 33, 36, 39, 42, 45
3015 .db 48, 51, 54, 57, 59, 62, 65, 67
3016 .db 70, 73, 75, 78, 80, 82, 85, 87
3017 .db 89, 91, 94, 96, 98,100,102,103
3018 .db 105,107,108,110,112,113,114,116
3019 .db 117,118,119,120,121,122,123,123
3020 .db 124,125,125,126,126,126,126,126
3023 txtLevel: .db "Level ",0
3024 txtWorms: .db "Worms: 0",0 ;follows txtLevel
3025 txtDied: .db "Died ",0
3026 txtScore: .db "Score",0 ;follows txtDied
3027 txtLeft: .db " left",0 ;follows txtScore
3028 txthiscore:.db "HiScore:",0
3029 txtReady: .db "Prepare!",0
3031 txtGO: .db "----- GAME OVER -----",0
3033 _datalink = %00000001 ;linkplay
3034 _datalivel = %00000010 ;lives=0 limit
3035 _datafoodl = %00000100 ;left=0 limit
3036 _datanextl = %00001000 ;next level if left=0
3037 _datasingl = %00001000 ;singleplayer=1
3038 ;1=hiscore+keep_length
3039 _datafood = %00010000 ;food present
3040 _datadie = %01000000 ;worm dies on impact
3041 _datascore = %10000000 ;score>=100 limit
3042 _datamultpeas = %00100000
3045 datalevels: .dw LevelDef, LevelDefM
3046 .dw LevelDefT,LevelDefM
3047 .dw LevelDefM,LevelDefM
3048 .dw LevelDefM,LevelDefM
3049 nrlevels: .db 1,2,2,2,2,2,2,1 ;=defaults
3054 datasingle: .db %01011110,3 ;3 lives (<must b unique)
3056 datapeas: .db %01011010,1 ;1 "
3058 datatron: .db %01000010,1
3060 datadeathm: .db %01000010,3
3062 datafoodm: .db %11010000,10 ;10 score limit (=100)
3064 datalinkm: .db %01000011,3
3066 datarace: .db %10000000,10
3068 datactf: .db %11100000,9
3070 ;datadomin: .db %01100000,3 ;==(8 modes)
3072 worm1set: .dw worm1p,worm1p
3073 .db %11110111,%00,%01111110,%10,%100 ;< >
3074 worm1name: .db "worm #01",0
3075 worm2set: .dw worm2p,worm2p
3076 .db %11111011,%11,%00111111,%10000,%1000 ;f1 f2
3077 worm2name: .db "worm #02",0
3078 worm3set: .dw worm3p,worm3p
3079 .db %11111011,0,%01011111,%10,%100 ;sto ,
3080 worm3name: .db "worm #03",0
3081 worm4set: .dw worm4p,worm4p
3082 .db %11111011,0,%01111101,%10,%1 ;enter +
3083 worm4name: .db "worm #04",0
3100 head = 13 ;4B (head=tail)
3101 tail = 15 ;also@next level
3116 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3117 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3118 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3119 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3120 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3121 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3122 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3123 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3124 .db "WWW.SHIAR.ORG WWW.SHIAR.ORG "
3125 .db " shiar0@hotmail.com",0
3128 defspriteimg: .db %01100000
3134 .db 15,"Internal Levels"
3136 .db 0,deflevels/256,deflevels&255
3139 ;-----------------------------
3140 ;----------- end -------------
3141 ;-----------------------------