mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-18 02:19:39 +00:00
loader: Only create gfx 4th bindings when gfx is available
Only create the gfx bindings for 4th when it's compiled into the loader. We do this with a linker set that only gets brought in to those loaders that call gfx_framework_init. This calls gfx_interp_md() will will drag in gfx_loader.c which will add to the linker set that registers these bindings. Sponsored by: Netflix Reviewed by: kevans, jhb Differential Revision: https://reviews.freebsd.org/D43904
This commit is contained in:
parent
60e199d9fd
commit
9c8bf69a53
@ -181,6 +181,7 @@ gfx_framework_init(void)
|
||||
* Setup font list to have builtin font.
|
||||
*/
|
||||
(void) insert_font(NULL, FONT_BUILTIN);
|
||||
gfx_interp_md(); /* Draw in the gfx interpreter for this thing */
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
|
@ -11,8 +11,8 @@ BASE_SRCS= dict.c ficl.c fileaccess.c float.c loader.c math64.c \
|
||||
SRCS= ${BASE_SRCS} sysdep.c softcore.c
|
||||
CLEANFILES+= softcore.c testmain testmain.o
|
||||
|
||||
CFLAGS.loader.c += -I${SRCTOP}/sys/teken
|
||||
CFLAGS.loader.c += -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.gfx_loader.c += -I${SRCTOP}/sys/teken
|
||||
CFLAGS.gfx_loader.c += -I${SRCTOP}/contrib/pnglite
|
||||
.ifmake testmain
|
||||
CFLAGS= -DTESTMAIN -D_TESTMAIN
|
||||
CFLAGS+= -I${FICLSRC} -I${FICLSRC}/${FICL_CPUARCH} -I${LDRSRC}
|
||||
@ -21,6 +21,7 @@ PROG= testmain
|
||||
.include <bsd.prog.mk>
|
||||
.else
|
||||
LIB= ficl
|
||||
BASE_SRCS+= gfx_loader.c # Not TESTMAINable
|
||||
.include <bsd.lib.mk>
|
||||
.endif
|
||||
|
||||
|
259
stand/ficl/gfx_loader.c
Normal file
259
stand/ficl/gfx_loader.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*-
|
||||
* Copyright (c) 2024 Netflix, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
/* Copied from a file that likely shoulve have had this at the top */
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright 2020 Toomas Soome
|
||||
* Copyright 2020 RackTop Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*******************************************************************
|
||||
** g f x _ l o a d e r . c
|
||||
** Additional FICL words designed for FreeBSD's loader
|
||||
** for graphics
|
||||
*******************************************************************/
|
||||
|
||||
#include <stand.h>
|
||||
#include "bootstrap.h"
|
||||
#include <gfx_fb.h>
|
||||
#include <pnglite.h>
|
||||
#include "ficl.h"
|
||||
|
||||
/* FreeBSD's loader interaction words and extras
|
||||
* for graphics
|
||||
* fb-bezier ( x0 y0 x1 y1 x2 y2 wd -- )
|
||||
* fb-drawrect ( x1 y1 x2 y2 fill -- )
|
||||
* fb-line ( x0 y0 x1 y1 wd -- )
|
||||
* fb-putimage ( flags x1 y1 x2 y2 -- flag )
|
||||
* fb-setpixel ( x y -- )
|
||||
* term-drawrect ( x1 y1 x2 y2 fill -- )
|
||||
* term-putimage ( flags x1 y1 x2 y2 -- flag )
|
||||
*/
|
||||
|
||||
/* ( flags x1 y1 x2 y2 -- flag ) */
|
||||
void
|
||||
ficl_term_putimage(FICL_VM *pVM)
|
||||
{
|
||||
char *namep, *name;
|
||||
int names;
|
||||
unsigned long ret = FICL_FALSE;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
png_t png;
|
||||
int error;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 1);
|
||||
#endif
|
||||
names = stackPopINT(pVM->pStack);
|
||||
namep = (char *) stackPopPtr(pVM->pStack);
|
||||
y2 = stackPopINT(pVM->pStack);
|
||||
x2 = stackPopINT(pVM->pStack);
|
||||
y1 = stackPopINT(pVM->pStack);
|
||||
x1 = stackPopINT(pVM->pStack);
|
||||
f = stackPopINT(pVM->pStack);
|
||||
|
||||
x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
|
||||
y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
|
||||
if (x2 != 0) {
|
||||
x2 = gfx_state.tg_origin.tp_col +
|
||||
x2 * gfx_state.tg_font.vf_width;
|
||||
}
|
||||
if (y2 != 0) {
|
||||
y2 = gfx_state.tg_origin.tp_row +
|
||||
y2 * gfx_state.tg_font.vf_height;
|
||||
}
|
||||
|
||||
name = ficlMalloc(names + 1);
|
||||
if (!name)
|
||||
vmThrowErr(pVM, "Error: out of memory");
|
||||
(void) strncpy(name, namep, names);
|
||||
name[names] = '\0';
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = FICL_TRUE; /* success */
|
||||
(void) png_close(&png);
|
||||
}
|
||||
ficlFree(name);
|
||||
stackPushUNS(pVM->pStack, ret);
|
||||
}
|
||||
|
||||
/* ( flags x1 y1 x2 y2 -- flag ) */
|
||||
void
|
||||
ficl_fb_putimage(FICL_VM *pVM)
|
||||
{
|
||||
char *namep, *name;
|
||||
int names;
|
||||
unsigned long ret = FICL_FALSE;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
png_t png;
|
||||
int error;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 1);
|
||||
#endif
|
||||
names = stackPopINT(pVM->pStack);
|
||||
namep = (char *) stackPopPtr(pVM->pStack);
|
||||
y2 = stackPopINT(pVM->pStack);
|
||||
x2 = stackPopINT(pVM->pStack);
|
||||
y1 = stackPopINT(pVM->pStack);
|
||||
x1 = stackPopINT(pVM->pStack);
|
||||
f = stackPopINT(pVM->pStack);
|
||||
|
||||
name = ficlMalloc(names + 1);
|
||||
if (!name)
|
||||
vmThrowErr(pVM, "Error: out of memory");
|
||||
(void) strncpy(name, namep, names);
|
||||
name[names] = '\0';
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = FICL_TRUE; /* success */
|
||||
(void) png_close(&png);
|
||||
}
|
||||
ficlFree(name);
|
||||
stackPushUNS(pVM->pStack, ret);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_setpixel(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x, y;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 2, 0);
|
||||
#endif
|
||||
|
||||
y = stackPopUNS(pVM->pStack);
|
||||
x = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_setpixel(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_line(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x0, y0, x1, y1, wd;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 5, 0);
|
||||
#endif
|
||||
|
||||
wd = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
y0 = stackPopUNS(pVM->pStack);
|
||||
x0 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_line(x0, y0, x1, y1, wd);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_bezier(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x0, y0, x1, y1, x2, y2, width;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 0);
|
||||
#endif
|
||||
|
||||
width = stackPopUNS(pVM->pStack);
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
y0 = stackPopUNS(pVM->pStack);
|
||||
x0 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_drawrect(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x1, x2, y1, y2, fill;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 5, 0);
|
||||
#endif
|
||||
|
||||
fill = stackPopUNS(pVM->pStack);
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_drawrect(x1, y1, x2, y2, fill);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_term_drawrect(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x1, x2, y1, y2;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 4, 0);
|
||||
#endif
|
||||
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
gfx_term_drawrect(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
f i c l C o m p i l e G f x
|
||||
** Build FreeBSD platform extensions into the system dictionary
|
||||
** for gfx
|
||||
**************************************************************************/
|
||||
static void ficlCompileGfx(FICL_SYSTEM *pSys)
|
||||
{
|
||||
ficlCompileFcn **fnpp;
|
||||
FICL_DICT *dp = pSys->dp;
|
||||
assert (dp);
|
||||
|
||||
dictAppendWord(dp, "fb-setpixel", ficl_fb_setpixel, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-line", ficl_fb_line, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-bezier", ficl_fb_bezier, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-drawrect", ficl_fb_drawrect, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-putimage", ficl_fb_putimage, FW_DEFAULT);
|
||||
dictAppendWord(dp, "term-drawrect", ficl_term_drawrect, FW_DEFAULT);
|
||||
dictAppendWord(dp, "term-putimage", ficl_term_putimage, FW_DEFAULT);
|
||||
|
||||
return;
|
||||
}
|
||||
FICL_COMPILE_SET(ficlCompileGfx);
|
||||
|
||||
void
|
||||
gfx_interp_md(void)
|
||||
{
|
||||
}
|
@ -44,8 +44,6 @@
|
||||
#include "bootstrap.h"
|
||||
#include <string.h>
|
||||
#include <uuid.h>
|
||||
#include <gfx_fb.h>
|
||||
#include <pnglite.h>
|
||||
#include "ficl.h"
|
||||
|
||||
/* FreeBSD's loader interaction words and extras
|
||||
@ -65,182 +63,6 @@
|
||||
* .# ( value -- )
|
||||
*/
|
||||
|
||||
#ifndef TESTMAIN
|
||||
/* ( flags x1 y1 x2 y2 -- flag ) */
|
||||
void
|
||||
ficl_term_putimage(FICL_VM *pVM)
|
||||
{
|
||||
char *namep, *name;
|
||||
int names;
|
||||
unsigned long ret = FICL_FALSE;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
png_t png;
|
||||
int error;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 1);
|
||||
#endif
|
||||
names = stackPopINT(pVM->pStack);
|
||||
namep = (char *) stackPopPtr(pVM->pStack);
|
||||
y2 = stackPopINT(pVM->pStack);
|
||||
x2 = stackPopINT(pVM->pStack);
|
||||
y1 = stackPopINT(pVM->pStack);
|
||||
x1 = stackPopINT(pVM->pStack);
|
||||
f = stackPopINT(pVM->pStack);
|
||||
|
||||
x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
|
||||
y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
|
||||
if (x2 != 0) {
|
||||
x2 = gfx_state.tg_origin.tp_col +
|
||||
x2 * gfx_state.tg_font.vf_width;
|
||||
}
|
||||
if (y2 != 0) {
|
||||
y2 = gfx_state.tg_origin.tp_row +
|
||||
y2 * gfx_state.tg_font.vf_height;
|
||||
}
|
||||
|
||||
name = ficlMalloc(names + 1);
|
||||
if (!name)
|
||||
vmThrowErr(pVM, "Error: out of memory");
|
||||
(void) strncpy(name, namep, names);
|
||||
name[names] = '\0';
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = FICL_TRUE; /* success */
|
||||
(void) png_close(&png);
|
||||
}
|
||||
ficlFree(name);
|
||||
stackPushUNS(pVM->pStack, ret);
|
||||
}
|
||||
|
||||
/* ( flags x1 y1 x2 y2 -- flag ) */
|
||||
void
|
||||
ficl_fb_putimage(FICL_VM *pVM)
|
||||
{
|
||||
char *namep, *name;
|
||||
int names;
|
||||
unsigned long ret = FICL_FALSE;
|
||||
uint32_t x1, y1, x2, y2, f;
|
||||
png_t png;
|
||||
int error;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 1);
|
||||
#endif
|
||||
names = stackPopINT(pVM->pStack);
|
||||
namep = (char *) stackPopPtr(pVM->pStack);
|
||||
y2 = stackPopINT(pVM->pStack);
|
||||
x2 = stackPopINT(pVM->pStack);
|
||||
y1 = stackPopINT(pVM->pStack);
|
||||
x1 = stackPopINT(pVM->pStack);
|
||||
f = stackPopINT(pVM->pStack);
|
||||
|
||||
name = ficlMalloc(names + 1);
|
||||
if (!name)
|
||||
vmThrowErr(pVM, "Error: out of memory");
|
||||
(void) strncpy(name, namep, names);
|
||||
name[names] = '\0';
|
||||
|
||||
if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
|
||||
if (f & FL_PUTIMAGE_DEBUG)
|
||||
printf("%s\n", png_error_string(error));
|
||||
} else {
|
||||
if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
|
||||
ret = FICL_TRUE; /* success */
|
||||
(void) png_close(&png);
|
||||
}
|
||||
ficlFree(name);
|
||||
stackPushUNS(pVM->pStack, ret);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_setpixel(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x, y;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 2, 0);
|
||||
#endif
|
||||
|
||||
y = stackPopUNS(pVM->pStack);
|
||||
x = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_setpixel(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_line(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x0, y0, x1, y1, wd;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 5, 0);
|
||||
#endif
|
||||
|
||||
wd = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
y0 = stackPopUNS(pVM->pStack);
|
||||
x0 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_line(x0, y0, x1, y1, wd);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_bezier(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x0, y0, x1, y1, x2, y2, width;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 7, 0);
|
||||
#endif
|
||||
|
||||
width = stackPopUNS(pVM->pStack);
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
y0 = stackPopUNS(pVM->pStack);
|
||||
x0 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_fb_drawrect(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x1, x2, y1, y2, fill;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 5, 0);
|
||||
#endif
|
||||
|
||||
fill = stackPopUNS(pVM->pStack);
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
gfx_fb_drawrect(x1, y1, x2, y2, fill);
|
||||
}
|
||||
|
||||
void
|
||||
ficl_term_drawrect(FICL_VM *pVM)
|
||||
{
|
||||
FICL_UNS x1, x2, y1, y2;
|
||||
|
||||
#if FICL_ROBUST > 1
|
||||
vmCheckStack(pVM, 4, 0);
|
||||
#endif
|
||||
|
||||
y2 = stackPopUNS(pVM->pStack);
|
||||
x2 = stackPopUNS(pVM->pStack);
|
||||
y1 = stackPopUNS(pVM->pStack);
|
||||
x1 = stackPopUNS(pVM->pStack);
|
||||
gfx_term_drawrect(x1, y1, x2, y2);
|
||||
}
|
||||
#endif /* TESTMAIN */
|
||||
|
||||
void
|
||||
ficlSetenv(FICL_VM *pVM)
|
||||
{
|
||||
@ -1042,16 +864,6 @@ void ficlCompilePlatform(FICL_SYSTEM *pSys)
|
||||
dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT);
|
||||
dictAppendWord(dp, "uuid-from-string", ficlUuidFromString, FW_DEFAULT);
|
||||
dictAppendWord(dp, "uuid-to-string", ficlUuidToString, FW_DEFAULT);
|
||||
#ifndef TESTMAIN
|
||||
dictAppendWord(dp, "fb-setpixel", ficl_fb_setpixel, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-line", ficl_fb_line, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-bezier", ficl_fb_bezier, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-drawrect", ficl_fb_drawrect, FW_DEFAULT);
|
||||
dictAppendWord(dp, "fb-putimage", ficl_fb_putimage, FW_DEFAULT);
|
||||
dictAppendWord(dp, "term-drawrect", ficl_term_drawrect, FW_DEFAULT);
|
||||
dictAppendWord(dp, "term-putimage", ficl_term_putimage, FW_DEFAULT);
|
||||
dictAppendWord(dp, "isvirtualized?",ficlIsvirtualizedQ, FW_DEFAULT);
|
||||
#endif
|
||||
|
||||
SET_FOREACH(fnpp, Xficl_compile_set)
|
||||
(*fnpp)(pSys);
|
||||
|
Loading…
Reference in New Issue
Block a user