New command line parameter parser now integrated into Linux.
This commit is contained in:
@@ -58,7 +58,7 @@ VIDEOBJ=${VIDEODIR}/makev16b.o ${VIDEODIR}/makev16t.o ${VIDEODIR}/makevid.o\
|
||||
WINOBJ=${WINDIR}/copyvwin.o \
|
||||
${WINDIR}/sdlintrf.o ${WINDIR}/sdllink.o \
|
||||
@GL_DRAW@ ${WINDIR}/sw_draw.o \
|
||||
${WINDIR}/zloaderw.o ${WINDIR}/zipxw.o ${WINDIR}/zfilew.o
|
||||
${WINDIR}/zipxw.o ${WINDIR}/zfilew.o
|
||||
|
||||
WINDOSOBJ=${DOSDIR}/debug.o ${DOSDIR}/joy.o ${DOSDIR}/modemrtn.o ${DOSDIR}/vesa2.o\
|
||||
${DOSDIR}/initvid.o ${DOSDIR}/sw.o ${DOSDIR}/gppro.o ${DOSDIR}/vesa12.o
|
||||
@@ -74,7 +74,7 @@ ZIPOBJ=${ZIPDIR}/unzip.o ${ZIPDIR}/zpng.o
|
||||
EFFECTSOBJ=${EFFECTSDIR}/burn.o ${EFFECTSDIR}/water.o ${EFFECTSDIR}/smoke.o
|
||||
|
||||
MAINOBJ=cfgload.o endmem.o init.o initc.o uic.o patch.o ui.o vcache.o version.o\
|
||||
zmovie.o zstate.o debug.o
|
||||
zmovie.o zstate.o debug.o zloader.o
|
||||
|
||||
OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${MAINOBJ} ${NETOBJ} ${ZIPOBJ} ${EFFECTSOBJ} ${JMAOBJ}
|
||||
|
||||
@@ -127,6 +127,7 @@ uic.o:uic.c
|
||||
patch.o:patch.c
|
||||
zmovie.o:zmovie.c
|
||||
zstate.o:zstate.c
|
||||
zloader.o:zloader.c
|
||||
|
||||
ALL:
|
||||
rm -f version.o
|
||||
|
||||
@@ -193,7 +193,7 @@ NEWSYM SystemInit
|
||||
call Change_Dir
|
||||
%endif
|
||||
|
||||
|
||||
|
||||
call GUIRestoreVars ; Load GUI stuff
|
||||
|
||||
call getcfg ; Load cfg stuff
|
||||
@@ -201,7 +201,6 @@ NEWSYM SystemInit
|
||||
call obtaindir ; Get Save/Init Directories
|
||||
|
||||
call ConvertJoyMap ; Mini joystick init
|
||||
call ccmdline
|
||||
call tparms
|
||||
pushad
|
||||
call SRAMChdir
|
||||
@@ -316,7 +315,7 @@ NEWSYM Open_File_Write
|
||||
NEWSYM Create_File
|
||||
pushad
|
||||
mov dword[ZOpenMode],1
|
||||
mov dword[ZOpenFileName],edx
|
||||
mov dword[ZOpenFileName],edx
|
||||
call ZOpenFile
|
||||
cmp eax,0FFFFFFFFh
|
||||
je .error
|
||||
@@ -432,7 +431,7 @@ NEWSYM Get_Date
|
||||
popad
|
||||
mov eax,[TempVarSeek]
|
||||
movzx edx,al ;Move day into edx, day is in BCD
|
||||
shr edx,4 ;Chop off the second digit
|
||||
shr edx,4 ;Chop off the second digit
|
||||
imul edx,10 ;Multiply first digit by 10, since we want decimal
|
||||
and al,0xF ;Remove first BCD digit
|
||||
add dl,al ;Add second digit to first*10
|
||||
@@ -678,7 +677,7 @@ NEWSYM Get_Memfree
|
||||
ret
|
||||
|
||||
NEWSYM Output_Text ; Output character (ah=02h) or string (ah=09h)
|
||||
pushad
|
||||
pushad
|
||||
|
||||
; This function usually displays an error message on-screen
|
||||
cmp ah,02h
|
||||
@@ -922,7 +921,7 @@ db '1280x1024 ODS F',0 ;16
|
||||
db '1600x1200 ODS F',0 ;17
|
||||
db 'VARIABLE ODR W',0 ;18
|
||||
|
||||
%endif
|
||||
%endif
|
||||
|
||||
; Video Mode Feature Availability (1 = Available, 0 = Not Available)
|
||||
; Left side starts with Video Mode 0
|
||||
@@ -1050,7 +1049,7 @@ NEWSYM ScanCodeListing
|
||||
db 'A0H','A1H','A2H','A3H','A4H','A5H','A6H','A7H' ; A0h
|
||||
db 'A8H','A9H','AAH','ABH','ACH','ADH','AEH','AFH'
|
||||
db 'B0H','B1H','B2H','B3H','B4H','B5H','B6H','B7H' ; B0h
|
||||
db 'B8H','B9H','BAH','BBH','BCH','BDH','BEH','BFH'
|
||||
db 'B8H','B9H','BAH','BBH','BCH','BDH','BEH','BFH'
|
||||
db 'C0H','C1H','C2H','C3H','C4H','C5H','C6H','C7H' ; C0h
|
||||
db 'C8H','C9H','CAH','CBH','CCH','CDH','CEH','CFH'
|
||||
db 'D0H','D1H','D2H','D3H','D4H','D5H','D6H','D7H' ; D0h
|
||||
@@ -1085,7 +1084,7 @@ NEWSYM ScanCodeListing
|
||||
db 'JA0','JA1','JA2','JA3','JA4','JA5','JA6','JA7' ; 2A0h
|
||||
db 'JA8','JA9','JAA','JAB','JAC','JAD','JAE','JAF'
|
||||
db 'JB0','JB1','JB2','JB3','JB4','JB5','JB6','JB7' ; 2B0h
|
||||
db 'JB8','JB9','JBA','JBB','JBC','JBD','JBE','JBF'
|
||||
db 'JB8','JB9','JBA','JBB','JBC','JBD','JBE','JBF'
|
||||
%else
|
||||
; Extra Stuff (180h) (Parallel Port)
|
||||
db 'PPB','PPY','PSL','PST','PUP','PDN','PLT','PRT' ; 180h
|
||||
@@ -1095,7 +1094,7 @@ NEWSYM ScanCodeListing
|
||||
db 'PPB','PPY','PSL','PST','PUP','PDN','PLT','PRT' ; 2A0h
|
||||
db 'PPA','PPX','PPL','PPR',' ',' ',' ',' '
|
||||
db 'P2B','P2Y','P2S','P2T','P2U','P2D','P2L','P2R' ; 2B0h
|
||||
db 'P2A','P2X','P2L','P2R',' ',' ',' ',' '
|
||||
db 'P2A','P2X','P2L','P2R',' ',' ',' ',' '
|
||||
%endif
|
||||
|
||||
SECTION .text
|
||||
@@ -1236,7 +1235,7 @@ NEWSYM SoundProcess ; This function is called ~60 times/s at full speed
|
||||
popad
|
||||
; DSPBuffer should contain the processed buffer in the specified size
|
||||
; You will have to convert/clip it to 16-bit for actual sound process
|
||||
.nosound
|
||||
.nosound
|
||||
popad
|
||||
ret
|
||||
|
||||
@@ -1252,7 +1251,7 @@ NEWSYM Check60hz
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
BitPosR db 11
|
||||
BitPosR db 11
|
||||
BitPosG db 5
|
||||
BitPosB db 0
|
||||
BitSizeR db 5
|
||||
@@ -1723,13 +1722,13 @@ NEWSYM WinErrorC
|
||||
NEWSYM GotoHomepage
|
||||
pushad
|
||||
call ZsnesPage
|
||||
popad
|
||||
popad
|
||||
ret
|
||||
|
||||
EXTSYM SystemTimewHour
|
||||
EXTSYM SystemTimewMinute
|
||||
EXTSYM SystemTimewSecond
|
||||
|
||||
|
||||
NEWSYM GetTimeInSeconds
|
||||
call GetLocalTime
|
||||
movzx eax,word[SystemTimewHour]
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 1997-2005 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
|
||||
This program 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 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
-------------
|
||||
Initial Linux Command Line Parsing by EvilTypeGuy (drevil@warpcore.org) April 2001
|
||||
*/
|
||||
|
||||
#include "gblhdr.h"
|
||||
|
||||
#define STUB_FUNCTION fprintf(stderr,"STUB: %s at " __FILE__ ", line %d, thread %d\n",__FUNCTION__,__LINE__,getpid())
|
||||
#define DWORD unsigned long
|
||||
#define _MAX_PATH 80
|
||||
#define _MAX_DRIVE 80
|
||||
#define _MAX_DIR 80
|
||||
#define _MAX_FNAME 80
|
||||
#define _MAX_EXT 80
|
||||
|
||||
extern void zstart(void);
|
||||
extern void DosExit(void);
|
||||
extern void ConvertJoyMap1(void);
|
||||
extern void ConvertJoyMap2(void);
|
||||
extern void displayparams(void);
|
||||
extern void makeextension(void);
|
||||
|
||||
extern unsigned char Palette0, SPC700sh, OffBy1Line, DSPDisable,
|
||||
MMXSupport, Force8b, ForcePal, ForceNTSC, GUIClick, MouseDis,
|
||||
MusicRelVol, ScreenScale, SoundQuality,
|
||||
StereoSound, V8Mode, antienab, cvidmode, debugdisble,
|
||||
debugger, enterpress, finterleave, frameskip,
|
||||
gammalevel, guioff, per2exec, pl1contrl, pl2contrl,
|
||||
romtype, scanlines, showallext, smallscreenon, soundon,
|
||||
spcon, vsyncon, DisplayS, fname, filefound, SnowOn,
|
||||
NetChatFirst,NetServer,NetNewNick,
|
||||
NetFilename,TCPIPAddress,NetQuitAfter,UDPConfig;
|
||||
|
||||
// FIX STATMAT
|
||||
extern unsigned char autoloadstate;
|
||||
// FIX STATMAT
|
||||
|
||||
int getopt(int argc, char *const argv[], const char *optstring);
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
void ccmdline(void);
|
||||
|
||||
char *ers[] =
|
||||
{
|
||||
"Frame Skip must be a value of 0 to 9!\n",
|
||||
"Gamma Correction Level must be a value of 0 to 5!\n",
|
||||
"Sound Sampling Rate must be a value of 0 to 5!\n",
|
||||
"Invalid Video Mode!\n",
|
||||
"Percentage of instructions to execute must be a number from 50 to 150!\n",
|
||||
"Player Input must be a value from 0 to 6!\n",
|
||||
"Volume must be a number from 0 to 100!\n"
|
||||
|
||||
};
|
||||
|
||||
//int argc;
|
||||
//char **argv;
|
||||
|
||||
char ucase(char ch){
|
||||
if ((ch>='a') && (ch<='z')) ch-='a'-'A';
|
||||
return(ch);
|
||||
}
|
||||
|
||||
int my_atoi(char *nptr) {
|
||||
int p,c;
|
||||
|
||||
c = 0;
|
||||
for(p = 0; nptr[p]; p++) {
|
||||
if ( !isdigit(nptr[p]) ) c += 1;
|
||||
}
|
||||
|
||||
if (c) return -1;
|
||||
|
||||
return atoi(nptr);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
int opt,p,pp;
|
||||
|
||||
char *fvar;
|
||||
|
||||
while((opt = getopt(argc, argv, "01:2:789a:c:d:ef:g:hijk:lmno:p:r:s:tuv:wyz?")) != -1) {
|
||||
switch(opt) {
|
||||
/* Palette 0 disable */
|
||||
case '0': {
|
||||
Palette0 = 1;
|
||||
break;
|
||||
}
|
||||
/* Player 1 Input */
|
||||
case '1': {
|
||||
//if (!hasroom) return 4;
|
||||
pl1contrl = my_atoi(optarg);
|
||||
|
||||
if (pl1contrl > 6) return 15;
|
||||
p++;
|
||||
|
||||
ConvertJoyMap1();
|
||||
break;
|
||||
}
|
||||
/* Player 2 Input */
|
||||
case '2': {
|
||||
// if (!hasroom) return 4;
|
||||
pl2contrl=my_atoi(optarg);
|
||||
|
||||
if (pl2contrl > 6) return 15;
|
||||
p++;
|
||||
|
||||
ConvertJoyMap2();
|
||||
break;
|
||||
}
|
||||
/* SPC700 speed hack disable */
|
||||
case '7': {
|
||||
SPC700sh = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case '8': {
|
||||
Force8b = 1;
|
||||
break;
|
||||
}
|
||||
/* Off by 1 line */
|
||||
case '9': {
|
||||
OffBy1Line = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c': {
|
||||
if (strcmp(optarg,"b") == 0) {
|
||||
printf("\nRemove background color in 256 modes not implemented!\n");
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
if (strcmp(optarg,"c") == 0) {
|
||||
smallscreenon = 1;
|
||||
pp++;
|
||||
} else {
|
||||
ScreenScale = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd': {
|
||||
if (strcmp(optarg,"d") == 0) {
|
||||
DSPDisable = 1;
|
||||
pp++;
|
||||
} else {
|
||||
/* debugger will never work under linux, since it's full of bios interrupt calls */
|
||||
printf("\nDebugger not implemented for Linux version!\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'e': {
|
||||
enterpress = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f': {
|
||||
// if (!hasroom) return 4;
|
||||
frameskip = my_atoi(optarg);
|
||||
if (frameskip > 9) return 10;
|
||||
frameskip++;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'g': {
|
||||
// if (!hasroom) return 4;
|
||||
gammalevel = my_atoi(optarg);
|
||||
|
||||
if (gammalevel > 5) return 11;
|
||||
p++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h': {
|
||||
romtype = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i': {
|
||||
finterleave = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'j': {
|
||||
GUIClick = 0;
|
||||
MouseDis = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'k': {
|
||||
// if (!hasroom) return 4;
|
||||
MusicRelVol = my_atoi(optarg);
|
||||
|
||||
if (MusicRelVol > 100) return 16;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l': {
|
||||
romtype = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* disables GUI */
|
||||
case 'm': {
|
||||
printf("Hello the gui should now be off.");
|
||||
guioff = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n': {
|
||||
scanlines = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o': {
|
||||
if (strcmp(optarg,"m") == 0) {
|
||||
MMXSupport = 1;
|
||||
pp++;
|
||||
} else {
|
||||
MMXSupport = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
// if (!hasroom) return 4;
|
||||
per2exec = my_atoi(optarg);
|
||||
|
||||
if (per2exec > 150) return 14;
|
||||
|
||||
if (per2exec < 50) return 14;
|
||||
p++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'r': {
|
||||
// if (!hasroom) return 4;
|
||||
SoundQuality = my_atoi(optarg);
|
||||
|
||||
if (SoundQuality > 6) return 12;
|
||||
p++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
if (strcmp(optarg,"a") == 0) {
|
||||
showallext = 1;
|
||||
pp++;
|
||||
} else if (strcmp(optarg,"n") == 0) {
|
||||
SnowOn = 1;
|
||||
pp++;
|
||||
} else {
|
||||
spcon = 1;
|
||||
soundon = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 't': {
|
||||
ForcePal = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'u': {
|
||||
ForcePal = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v': {
|
||||
if (strcmp(optarg,"8") == 0) {
|
||||
V8Mode = 1;
|
||||
pp++;
|
||||
} else {
|
||||
// if (!hasroom) return 4;
|
||||
cvidmode = my_atoi(optarg);
|
||||
|
||||
if (cvidmode > 10) return 13;
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w': {
|
||||
vsyncon = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'y': {
|
||||
antienab = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'z': {
|
||||
// FIX STATMAT
|
||||
// if((argv[p+1]) == 's')
|
||||
// {
|
||||
// if(!hasroom) return 4;
|
||||
// autoloadstate=my_atoi(argv[p+1]) + 1;
|
||||
// p++;
|
||||
// }
|
||||
|
||||
StereoSound=0;
|
||||
|
||||
// FIX STATMAT
|
||||
break;
|
||||
}
|
||||
|
||||
case '?': {
|
||||
displayparams();
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* execute rom filename: file.x */
|
||||
/* getopt permutates argv until all non options are at the end of argv. */
|
||||
/* since we only expect one non option, it should be the last argument. */
|
||||
if ( optind == argc - 1 && argv[optind] != NULL)
|
||||
{
|
||||
fvar=&fname;
|
||||
fvar[0] = strlen(argv[optind]);
|
||||
strncpy(&fvar[1], argv[optind],127);
|
||||
makeextension();
|
||||
}
|
||||
|
||||
zstart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pccmdline(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ccmdline(void) {
|
||||
int p = 0;
|
||||
|
||||
p = pccmdline();
|
||||
if (p == 0) return;
|
||||
|
||||
if (p == 9) {
|
||||
displayparams();
|
||||
}
|
||||
|
||||
if (p == 4) {
|
||||
/* printf("Mangled command line, did you forget a parm?\n"); */
|
||||
printf("Invalid Commandline!\n");
|
||||
DosExit();
|
||||
}
|
||||
|
||||
if ((p > 9) && (p < 17)) {
|
||||
printf(ers[p-10]);
|
||||
DosExit();
|
||||
}
|
||||
|
||||
if (p == 2) {
|
||||
DosExit();
|
||||
}
|
||||
|
||||
printf("cmdline returned %i\n",p);
|
||||
DosExit();
|
||||
}
|
||||
@@ -47,7 +47,7 @@ extern unsigned char Palette0, pl1contrl, pl2contrl, MMXSupport, Force8b, ForceP
|
||||
MouseDis, MusicRelVol, ScreenScale, SoundQuality, StereoSound, V8Mode,
|
||||
antienab, cvidmode, debugdisble, debugger, enterpress, vsyncon, DisplayS,
|
||||
fname, SnowOn, Triplebufen, SPC700sh, OffBy1Line, DSPDisable, frameskip,
|
||||
gammalevel, guioff, forceromtype, per2exec, scanlines, soundon, spcon,
|
||||
gammalevel, guioff, romtype, per2exec, scanlines, soundon, spcon,
|
||||
showallext, autoloadstate, smallscreenon;
|
||||
|
||||
void ConvertJoyMap1(), ConvertJoyMap2(), zstart(), makeextension();
|
||||
@@ -164,16 +164,18 @@ static void display_help()
|
||||
puts(" File Formats Supported by GUI : SMC,SFC,SWC,FIG,MGD,UFO,BIN,");
|
||||
puts(" 058,078,1,USA,EUR,JAP,ZIP,JMA");
|
||||
puts("");
|
||||
#ifndef __LINUX__
|
||||
puts(" Microsoft-style options (/option) are also accepted");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static size_t zatoi(const char *str)
|
||||
{
|
||||
const char *orig_str = str;
|
||||
while (*str++)
|
||||
while (*str)
|
||||
{
|
||||
if (!isdigit(*str)) { return(~0); }
|
||||
if (!isdigit(*str++)) { return(~0); }
|
||||
}
|
||||
return((size_t)atoi(orig_str));
|
||||
}
|
||||
@@ -187,7 +189,7 @@ static void handle_params(int argc, const char **argv)
|
||||
NetChatFirst=0;
|
||||
NetQuitAfter=0;
|
||||
|
||||
if (argv[1][0] == '/' && strlen(argv[1]) == 6)
|
||||
if (argc >= 5 && argv[1][0] == '/' && strlen(argv[1]) == 6)
|
||||
{
|
||||
size_t i = 0, j = 0;
|
||||
char *strp, *p;
|
||||
@@ -261,7 +263,7 @@ static void handle_params(int argc, const char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
#ifndef __LINUX__
|
||||
if (argv[i][0] == '-' || argv[i][0] == '/')
|
||||
@@ -356,7 +358,7 @@ static void handle_params(int argc, const char **argv)
|
||||
break;
|
||||
|
||||
case 'h': //Force HiROM
|
||||
forceromtype = 2;
|
||||
romtype = 2;
|
||||
break;
|
||||
|
||||
case 'j': //Disable Mouse
|
||||
@@ -374,7 +376,7 @@ static void handle_params(int argc, const char **argv)
|
||||
break;
|
||||
|
||||
case 'l': //Force LoROM
|
||||
forceromtype = 1;
|
||||
romtype = 1;
|
||||
break;
|
||||
|
||||
case 'm': //Disables GUI
|
||||
@@ -522,6 +524,7 @@ static void handle_params(int argc, const char **argv)
|
||||
char *fvar = &fname;
|
||||
fvar[0] = strlen(argv[i]);
|
||||
strncpy(&fvar[1],argv[i],127);
|
||||
makeextension();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -544,7 +547,6 @@ int main(int argc, const char **argv)
|
||||
{
|
||||
handle_params(argc, argv);
|
||||
|
||||
makeextension();
|
||||
zstart();
|
||||
return(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user