Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
W
wolf3d
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PocketInsanity
wolf3d
Commits
d8c795c6
Commit
d8c795c6
authored
May 21, 2000
by
Steven Fuller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Yay, the game is now playable and does not crash
parent
585c01d7
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
270 additions
and
50 deletions
+270
-50
InterMis.c
macsrc/InterMis.c
+6
-2
Level.c
macsrc/Level.c
+1
-1
Makefile
macsrc/Makefile
+2
-0
RefSprite.c
macsrc/RefSprite.c
+4
-4
Refresh.c
macsrc/Refresh.c
+1
-1
TODO
macsrc/TODO
+9
-1
burger.h
macsrc/burger.h
+1
-0
vi_svga.c
macsrc/vi_svga.c
+234
-32
wolfdef.h
macsrc/wolfdef.h
+12
-9
No files found.
macsrc/InterMis.c
View file @
d8c795c6
...
...
@@ -225,19 +225,23 @@ void LevelCompleted (void)
NumberIndex
=
47
;
/* Hack to draw score using an alternate number set */
NewGameWindow
(
1
);
/* Force 512 mode screen */
PackPtr
=
LoadAResource
(
rIntermission
);
PackLength
=
PackPtr
[
0
]
;
PackLength
=
lMSB
(
PackPtr
[
0
])
;
ShapePtr
=
(
Byte
*
)
AllocSomeMem
(
PackLength
);
DLZSS
(
ShapePtr
,(
Byte
*
)
&
PackPtr
[
1
],
PackLength
);
DrawShape
(
0
,
0
,
ShapePtr
);
FreeSomeMem
(
ShapePtr
);
ReleaseAResource
(
rIntermission
);
PackPtr
=
LoadAResource
(
rInterPics
);
PackLength
=
PackPtr
[
0
]
;
PackLength
=
lMSB
(
PackPtr
[
0
])
;
BJPtr
=
(
Byte
*
)
AllocSomeMem
(
PackLength
);
DLZSS
(
BJPtr
,(
Byte
*
)
&
PackPtr
[
1
],
PackLength
);
ReleaseAResource
(
rInterPics
);
memcpy
(
Indexs
,
BJPtr
,
12
);
/* Copy the index table */
Indexs
[
0
]
=
lMSB
(
Indexs
[
0
]);
Indexs
[
1
]
=
lMSB
(
Indexs
[
1
]);
Indexs
[
2
]
=
lMSB
(
Indexs
[
2
]);
WhichBJ
=
0
;
/* Init BJ */
BJTime
=
ReadTick
()
-
50
;
/* Force a redraw */
BlastScreen
();
/* Draw the screen */
...
...
macsrc/Level.c
View file @
d8c795c6
...
...
@@ -592,7 +592,7 @@ Boolean SetupGameLevel(void)
dest
=
&
tilemap
[
0
][
0
];
Count
=
0
;
do
{
tile
=
src
[
Count
];
/* Get the byte tile */
tile
=
src
[
Count
];
if
(
tile
&
TI_BLOCKMOVE
)
{
tile
|=
TI_BLOCKSIGHT
;
/* Mark as blocking my sight */
WallHits
[(
tile
-
1
)
&
0x1F
]
=
1
;
...
...
macsrc/Makefile
View file @
d8c795c6
...
...
@@ -2,6 +2,7 @@ CC = gcc
#CFLAGS = -Wall -O6 -fomit-frame-pointer -ffast-math -funroll-loops -mpentiumpro -mcpu=pentiumpro -march=pentiumpro
#CFLAGS = -g -Wall
#CFLAGS = -g -DNOVGA
CFLAGS
=
-g
#CFLAGS = -Os
#CFLAGS = -g -Wall -I/home/relnev/cvs/oal/include
...
...
@@ -16,6 +17,7 @@ GOBJS = $(OBJS)
LFLAGS
=
-lm
#LFLAGS = -lm -L/home/relnev/cvs/oal/linux/src -lopenal -lpthread -ldl
#LFLAGS = -lm /home/relnev/ElectricFence-2.2.2/libefence.a -lpthread
SLFLAGS
=
$(LFLAGS)
-lvga
XLFLAGS
=
$(LFLAGS)
-L
/usr/X11R6/lib
-lX11
-lXext
-lXxf86vm
-lXxf86dga
...
...
macsrc/RefSprite.c
View file @
d8c795c6
...
...
@@ -186,7 +186,7 @@ void AddSprite (thing_t *thing,Word actornum)
patch
=
SpriteArray
[
thing
->
sprite
];
/* Pointer to the sprite info */
width
=
((
LongWord
)
patch
[
0
]
*
scale
)
>>
6
;
/* Get the width of the shape */
width
=
((
LongWord
)
sMSB
(
patch
[
0
])
*
scale
)
>>
6
;
/* Get the width of the shape */
if
(
!
width
)
{
return
;
/* too far away*/
}
...
...
@@ -203,7 +203,7 @@ void AddSprite (thing_t *thing,Word actornum)
VisPtr
->
x1
=
x1
;
/* Min x */
VisPtr
->
x2
=
x2
;
/* Max x */
VisPtr
->
clipscale
=
scale
;
/* Size to draw */
VisPtr
->
columnstep
=
(
patch
[
0
]
<<
8
)
/
width
;
/* Step for width scale */
VisPtr
->
columnstep
=
(
sMSB
(
patch
[
0
])
<<
8
)
/
width
;
/* Step for width scale */
VisPtr
->
actornum
=
actornum
;
/* Actor who this is (0 for static) */
/* pack the vissprite number into the low 6 bits of the scale for sorting */
...
...
@@ -231,7 +231,7 @@ void DrawTopSprite(void)
patch
=
SpriteArray
[
topspritenum
];
/* Get the info on the shape */
width
=
(
patch
[
0
]
*
topspritescale
)
>>
7
;
/* Adjust the width */
width
=
(
sMSB
(
patch
[
0
])
*
topspritescale
)
>>
7
;
/* Adjust the width */
if
(
!
width
)
{
return
;
/* Too far away */
}
...
...
@@ -247,7 +247,7 @@ void DrawTopSprite(void)
VisRecord
.
x1
=
x1
;
/* Left edge */
VisRecord
.
x2
=
x2
;
/* Right edge */
VisRecord
.
clipscale
=
topspritescale
;
/* Size */
VisRecord
.
columnstep
=
(
patch
[
0
]
<<
8
)
/
(
x2
-
x1
+
1
);
/* Width step */
VisRecord
.
columnstep
=
(
sMSB
(
patch
[
0
])
<<
8
)
/
(
x2
-
x1
+
1
);
/* Width step */
/* Make sure it is sorted to be drawn last */
...
...
macsrc/Refresh.c
View file @
d8c795c6
...
...
@@ -216,7 +216,7 @@ Boolean StartupRendering(Word NewSize)
/* viewangle tangent table*/
if
(
MathSize
==-
1
)
{
/* Only needs to be done once */
if
(
MathSize
==
(
Word
)
-
1
)
{
/* Only needs to be done once */
i
=
0
;
do
{
a
=
(
i
-
FINEANGLES
/
4
+
0
.
1
)
*
PI
*
2
/
FINEANGLES
;
...
...
macsrc/TODO
View file @
d8c795c6
* WaitTick only called in nonplay modes and ReadSystemJoystick in playmode
* remove NOVGA when other ports are added. NOVGA is a hack for using
ElectricFence (since svgalib doesn't work too well with it)
* finish defining all the keys
* when you die, where do all the sprites go?
* drawing seems like its imprecise, stationary sprites move back and forth,
and walls 'swim' when you move around
* Word is 16bit damnit, wonder why in the MAC version its 32bits?!
* Automap movement is too fast
* How about adding red/white shifts (from PC wolf3d)?
\ No newline at end of file
macsrc/burger.h
View file @
d8c795c6
...
...
@@ -2,6 +2,7 @@ typedef unsigned int Word;
typedef
unsigned
long
LongWord
;
typedef
unsigned
char
Byte
;
typedef
unsigned
char
Boolean
;
typedef
unsigned
short
int
SWord
;
#define BLACK 255
#define DARKGREY 250
...
...
macsrc/vi_svga.c
View file @
d8c795c6
...
...
@@ -8,6 +8,8 @@
Byte
*
gfxbuf
;
void
keyboard_handler
(
int
key
,
int
press
);
void
FixMapList
(
maplist_t
*
m
)
{
int
i
;
...
...
@@ -54,20 +56,38 @@ ReleaseAResource(MySoundList);
WallListPtr
=
(
unsigned
short
*
)
LoadAResource
(
MyWallList
);
NewGameWindow
(
0
);
/* 320x200 */
//#ifndef NOVGA
keyboard_init
();
/* keyboard must be init'd after vga_setmode .. */
keyboard_seteventhandler
(
keyboard_handler
);
//#endif
ClearTheScreen
(
BLACK
);
BlastScreen
();
return
WolfMain
(
argc
,
argv
);
}
void
Quit
(
char
*
str
)
{
keyboard_close
();
vga_setmode
(
TEXT
);
if
(
str
&&
*
str
)
{
fprintf
(
stderr
,
"%s
\n
"
,
str
);
exit
(
EXIT_FAILURE
);
}
exit
(
EXIT_SUCCESS
);
}
void
SetPalette
(
Byte
*
pal
)
{
int
i
;
vga_waitretrace
();
#ifndef NOVGA
for
(
i
=
0
;
i
<
256
;
i
++
)
vga_setpalette
(
i
,
pal
[
i
*
3
+
0
]
>>
2
,
pal
[
i
*
3
+
1
]
>>
2
,
pal
[
i
*
3
+
2
]
>>
2
);
#endif
}
void
BlastScreen2
(
Rect
*
BlastRect
)
...
...
@@ -75,54 +95,54 @@ void BlastScreen2(Rect *BlastRect)
BlastScreen
();
}
static
int
w
,
h
;
static
int
w
,
h
,
v
;
void
BlastScreen
()
{
Byte
*
ptrs
=
gfxbuf
,
*
ptrd
=
graph_mem
;
int
i
;
int
i
;
#ifndef NOVGA
for
(
i
=
0
;
i
<
200
;
i
++
)
{
memcpy
(
ptrd
,
ptrs
,
320
);
ptrs
+=
w
;
ptrd
+=
320
;
}
#endif
}
Word
VidXs
[]
=
{
320
,
512
,
640
,
640
};
/* Screen sizes to play with */
Word
VidYs
[]
=
{
200
,
384
,
400
,
480
};
Word
VidVs
[]
=
{
160
,
320
,
320
,
400
};
Word
VidPics
[]
=
{
rFaceShapes
,
rFace512
,
rFace640
,
rFace640
};
Word
VidSize
=
-
1
;
Word
NewGameWindow
(
Word
NewVidSize
)
{
LongWord
*
LongPtr
;
Byte
*
DestPtr
;
int
i
;
switch
(
NewVidSize
)
{
case
0
:
w
=
320
;
h
=
200
;
break
;
case
1
:
w
=
512
;
h
=
384
;
break
;
case
2
:
w
=
640
;
h
=
400
;
break
;
case
3
:
w
=
640
;
h
=
480
;
break
;
default:
fprintf
(
stderr
,
"Vid size: %d
\n
"
,
NewVidSize
);
exit
(
EXIT_FAILURE
);
if
(
NewVidSize
==
VidSize
)
return
VidSize
;
if
(
NewVidSize
<
4
)
{
w
=
VidXs
[
NewVidSize
];
h
=
VidYs
[
NewVidSize
];
v
=
VidVs
[
NewVidSize
];
}
else
{
fprintf
(
stderr
,
"Vid size: %d
\n
"
,
NewVidSize
);
exit
(
EXIT_FAILURE
);
}
if
(
gfxbuf
)
free
(
gfxbuf
);
gfxbuf
=
(
Byte
*
)
malloc
(
w
*
h
);
#ifndef NOVGA
vga_setmode
(
G320x200x256
);
#endif
VideoPointer
=
gfxbuf
;
VideoWidth
=
w
;
...
...
@@ -131,7 +151,7 @@ Word NewGameWindow(Word NewVidSize)
ClearTheScreen
(
BLACK
);
BlastScreen
();
LongPtr
=
(
LongWord
*
)
LoadAResource
(
rFaceShapes
);
LongPtr
=
(
LongWord
*
)
LoadAResource
(
VidPics
[
NewVidSize
]
);
GameShapes
=
(
Byte
**
)
AllocSomeMem
(
lMSB
(
LongPtr
[
0
]));
DLZSS
((
Byte
*
)
GameShapes
,(
Byte
*
)
&
LongPtr
[
1
],
lMSB
(
LongPtr
[
0
]));
...
...
@@ -142,19 +162,127 @@ Word NewGameWindow(Word NewVidSize)
for
(
i
=
0
;
i
<
((
NewVidSize
==
1
)
?
57
:
47
);
i
++
)
GameShapes
[
i
]
=
DestPtr
+
lMSB
(
LongPtr
[
i
]);
return
0
;
VidSize
=
NewVidSize
;
return
VidSize
;
}
void
IO_ScaleWallColumn
(
Word
x
,
Word
scale
,
Word
tile
,
Word
column
)
LongWord
ScaleDiv
[
2048
];
void
ScaledDraw
(
Byte
*
gfx
,
Word
scale
,
Byte
*
vid
,
LongWord
TheFrac
,
Word
TheInt
,
Word
Width
,
LongWord
Delta
)
{
LongWord
OldDelta
;
while
(
scale
--
)
{
*
vid
=
*
gfx
;
vid
+=
Width
;
OldDelta
=
Delta
;
Delta
+=
TheFrac
;
gfx
+=
TheInt
;
if
(
OldDelta
>
Delta
)
gfx
+=
1
;
}
}
void
IO_ScaleWallColumn
(
Word
x
,
Word
scale
,
Word
tile
,
Word
column
)
{
LongWord
TheFrac
;
Word
TheInt
;
LongWord
y
;
Byte
*
ArtStart
;
if
(
scale
)
{
scale
*=
2
;
TheFrac
=
0x80000000UL
/
scale
;
ArtStart
=
&
ArtData
[
tile
][
column
<<
7
];
if
(
scale
<
VIEWHEIGHT
)
{
y
=
(
VIEWHEIGHT
-
scale
)
/
2
;
TheInt
=
TheFrac
>>
24
;
TheFrac
<<=
8
;
ScaledDraw
(
ArtStart
,
scale
,
&
VideoPointer
[(
y
*
VideoWidth
)
+
x
],
TheFrac
,
TheInt
,
VideoWidth
,
0
);
return
;
}
y
=
(
scale
-
VIEWHEIGHT
)
/
2
;
y
=
y
*
TheFrac
;
TheInt
=
TheFrac
>>
24
;
TheFrac
<<=
8
;
ScaledDraw
(
&
ArtStart
[
y
>>
24
],
VIEWHEIGHT
,
&
VideoPointer
[
x
],
TheFrac
,
TheInt
,
VideoWidth
,
y
<<
8
);
}
}
void
IO_ScaleMaskedColumn
(
Word
x
,
Word
scale
,
unsigned
short
*
sprite
,
Word
column
)
typedef
struct
{
SWord
Topy
;
SWord
Boty
;
SWord
Shape
;
}
PACKED
SpriteRun
;
void
IO_ScaleMaskedColumn
(
Word
x
,
Word
scale
,
unsigned
short
*
CharPtr
,
Word
column
)
{
Byte
*
CharPtr2
;
int
Y1
,
Y2
;
Byte
*
Screenad
;
SpriteRun
*
RunPtr
;
LongWord
TheFrac
;
LongWord
TFrac
;
LongWord
TInt
;
Word
RunCount
;
int
TopY
;
Word
Index
;
LongWord
Delta
;
if
(
!
scale
)
return
;
CharPtr2
=
(
Byte
*
)
CharPtr
;
TheFrac
=
ScaleDiv
[
scale
];
RunPtr
=
(
SpriteRun
*
)
&
CharPtr
[
sMSB
(
CharPtr
[
column
+
1
])
/
2
];
Screenad
=
&
VideoPointer
[
x
];
TFrac
=
TheFrac
<<
8
;
TInt
=
TheFrac
>>
24
;
TopY
=
(
VIEWHEIGHT
/
2
)
-
scale
;
while
(
RunPtr
->
Topy
!=
0xFFFF
)
{
Y1
=
scale
*
(
LongWord
)
sMSB
(
RunPtr
->
Topy
)
/
128
+
TopY
;
if
(
Y1
<
(
int
)
VIEWHEIGHT
)
{
Y2
=
scale
*
(
LongWord
)
sMSB
(
RunPtr
->
Boty
)
/
128
+
TopY
;
if
(
Y2
>
0
)
{
if
(
Y2
>
(
int
)
VIEWHEIGHT
)
Y2
=
VIEWHEIGHT
;
Index
=
sMSB
(
RunPtr
->
Shape
)
+
sMSB
(
RunPtr
->
Topy
)
/
2
;
Delta
=
0
;
if
(
Y1
<
0
)
{
Delta
=
(
0
-
(
LongWord
)
Y1
)
*
TheFrac
;
Index
+=
(
Delta
>>
24
);
Delta
<<=
8
;
Y1
=
0
;
}
RunCount
=
Y2
-
Y1
;
if
(
RunCount
)
ScaledDraw
(
&
CharPtr2
[
Index
],
RunCount
,
&
Screenad
[
Y1
*
VideoWidth
],
TFrac
,
TInt
,
VideoWidth
,
Delta
);
}
}
RunPtr
++
;
}
}
Boolean
SetupScalers
(
void
)
{
Word
i
;
if
(
!
ScaleDiv
[
1
])
{
i
=
1
;
do
{
ScaleDiv
[
i
]
=
0x40000000
/
i
;
}
while
(
++
i
<
2048
);
MaxScaler
=
2048
;
}
return
1
;
}
...
...
@@ -167,19 +295,93 @@ void FlushKeys(void)
/* TODO: read all keys in keyboard buffer */
}
static
int
RSJ
;
static
int
keys
[
128
];
void
keyboard_handler
(
int
key
,
int
press
)
{
if
(
key
==
SCANCODE_Q
)
Quit
(
"blah"
);
if
(
RSJ
)
{
keys
[
key
]
=
press
;
joystick1
=
0
;
if
(
press
==
0
)
{
switch
(
key
)
{
case
SCANCODE_1
:
gamestate
.
pendingweapon
=
WP_KNIFE
;
break
;
case
SCANCODE_2
:
if
(
gamestate
.
ammo
)
{
gamestate
.
pendingweapon
=
WP_PISTOL
;
}
break
;
case
SCANCODE_3
:
if
(
gamestate
.
ammo
&&
gamestate
.
machinegun
)
{
gamestate
.
pendingweapon
=
WP_MACHINEGUN
;
}
break
;
case
SCANCODE_4
:
if
(
gamestate
.
ammo
&&
gamestate
.
chaingun
)
{
gamestate
.
pendingweapon
=
WP_CHAINGUN
;
}
break
;
case
SCANCODE_5
:
if
(
gamestate
.
gas
&&
gamestate
.
flamethrower
)
{
gamestate
.
pendingweapon
=
WP_FLAMETHROWER
;
}
break
;
case
SCANCODE_6
:
if
(
gamestate
.
missiles
&&
gamestate
.
missile
)
{
gamestate
.
pendingweapon
=
WP_MISSILE
;
}
break
;
case
SCANCODE_PERIOD
:
case
SCANCODE_SLASH
:
joystick1
=
JOYPAD_START
;
break
;
}
}
if
(
keys
[
SCANCODE_CURSORBLOCKLEFT
])
joystick1
|=
JOYPAD_LFT
;
if
(
keys
[
SCANCODE_CURSORBLOCKRIGHT
])
joystick1
|=
JOYPAD_RGT
;
if
(
keys
[
SCANCODE_CURSORBLOCKUP
])
joystick1
|=
JOYPAD_UP
;
if
(
keys
[
SCANCODE_CURSORBLOCKDOWN
])
joystick1
|=
JOYPAD_DN
;
if
(
keys
[
SCANCODE_SPACE
])
joystick1
|=
JOYPAD_A
;
if
(
keys
[
SCANCODE_LEFTCONTROL
])
joystick1
|=
JOYPAD_B
;
}
}
void
ReadSystemJoystick
(
void
)
{
/* TODO: do key stuff here */
RSJ
=
1
;
//#ifndef NOVGA
keyboard_update
();
//#endif
}
/*
Handle events, and return:
last keypress (if any)
last keypress (if any)
in ascii
mouse button events == 1
zero means none of the above
*/
int
DoEvents
()
{
return
0
;
RSJ
=
0
;
//#ifndef NOVGA
keyboard_update
();
//#endif
/* TODO: hack */
return
'B'
;
}
macsrc/wolfdef.h
View file @
d8c795c6
...
...
@@ -8,6 +8,8 @@
#define FALSE 0
#endif
#define PACKED __attribute__((packed))
typedef
struct
{
int
left
;
int
top
;
...
...
@@ -272,7 +274,7 @@ typedef struct {
unsigned
short
numnodes
;
/* Must be short */
unsigned
short
nodelistofs
;
/* Must be short */
Byte
data
[
1
];
/* nodes, and spawn list */
}
loadmap_t
;
}
PACKED
loadmap_t
;
typedef
struct
{
unsigned
short
NextLevel
;
/* Normal warp level */
...
...
@@ -280,13 +282,13 @@ typedef struct {
unsigned
short
ParTime
;
/* Time for par */
unsigned
short
ScenarioNum
;
/* Scenario number */
unsigned
short
FloorNum
;
/* Floor number */
}
MapInfo_t
;
}
PACKED
MapInfo_t
;
typedef
struct
{
unsigned
short
MaxMap
;
/* Maximum number of maps */
unsigned
short
MapRezNum
;
/* Basic resource # */
MapInfo_t
InfoArray
[
1
];
/* Next map to jump to */
}
maplist_t
;
}
PACKED
maplist_t
;
/**********************************
...
...
@@ -327,16 +329,16 @@ typedef struct {
Byte
plane
;
Byte
dir
;
unsigned
short
children
[
2
];
}
savenode_t
;
}
PACKED
savenode_t
;
#ifndef __BIGENDIAN__
#ifndef __BIGENDIAN__
typedef
struct
{
Byte
plane
;
/* in half tiles*/
Byte
dir
;
Byte
min
,
max
;
/* in half tiles*/
Byte
texture
;
Byte
area
;
}
saveseg_t
;
}
PACKED
saveseg_t
;
#else
typedef
struct
{
Byte
plane
;
/* in half tiles*/
...
...
@@ -344,7 +346,7 @@ typedef struct {
Byte
max
,
min
;
/* in half tiles*/
Byte
area
;
Byte
texture
;
}
saveseg_t
;
}
PACKED
saveseg_t
;
#endif
/**********************************
...
...
@@ -356,8 +358,9 @@ typedef struct {
/* Used by the renderer, must match the header of static_t, actor_t, missile_t */
/* TODO: hrm */
typedef
struct
{
int
x
,
y
;
/* Item's x,y */
Word
x
,
y
;
/* Item's x,y */
Word
sprite
;
/* Item's shape */
Word
areanumber
;
/* Item's visible area */
}
thing_t
;
...
...
@@ -697,7 +700,7 @@ extern void IO_DisplayViewBuffer(void);
extern
Boolean
BuildCompScale
(
Word
height
,
void
**
finalspot
,
Byte
*
WorkPtr
);
extern
Boolean
SetupScalers
(
void
);
extern
void
ReleaseScalers
(
void
);
extern
void
IO_ScaleMaskedColumn
(
Word
x
,
Word
scale
,
unsigned
short
*
sprite
,
Word
column
);
extern
void
IO_ScaleMaskedColumn
(
Word
x
,
Word
scale
,
unsigned
short
*
sprite
,
Word
column
);
extern
void
DrawSmall
(
Word
x
,
Word
y
,
Word
tile
);
extern
void
MakeSmallFont
(
void
);
extern
void
KillSmallFont
(
void
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment