Пример #1
0
void rfx_decode_rgb(RFX_CONTEXT* context, STREAM* data_in,
	int y_size, const uint32 * y_quants,
	int cb_size, const uint32 * cb_quants,
	int cr_size, const uint32 * cr_quants, uint8* rgb_buffer)
{
	PROFILER_ENTER(context->priv->prof_rfx_decode_rgb);

	rfx_decode_component(context, y_quants, stream_get_tail(data_in), y_size, context->priv->y_r_buffer); /* YData */
	stream_seek(data_in, y_size);
	rfx_decode_component(context, cb_quants, stream_get_tail(data_in), cb_size, context->priv->cb_g_buffer); /* CbData */
	stream_seek(data_in, cb_size);
	rfx_decode_component(context, cr_quants, stream_get_tail(data_in), cr_size, context->priv->cr_b_buffer); /* CrData */
	stream_seek(data_in, cr_size);

	PROFILER_ENTER(context->priv->prof_rfx_decode_ycbcr_to_rgb);
		context->decode_ycbcr_to_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer);
	PROFILER_EXIT(context->priv->prof_rfx_decode_ycbcr_to_rgb);

	PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb);
		rfx_decode_format_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer,
			context->pixel_format, rgb_buffer);
	PROFILER_EXIT(context->priv->prof_rfx_decode_format_rgb);
	
	PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);
}
Пример #2
0
static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values,
	const BYTE* data, int size, INT16* buffer)
{
	INT16* dwt_buffer;

	dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */

	PROFILER_ENTER(context->priv->prof_rfx_decode_component);

	PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode);
		context->rlgr_decode(context->mode, data, size, buffer, 4096);
	PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode);

	PROFILER_ENTER(context->priv->prof_rfx_differential_decode);
		rfx_differential_decode(buffer + 4032, 64);
	PROFILER_EXIT(context->priv->prof_rfx_differential_decode);

	PROFILER_ENTER(context->priv->prof_rfx_quantization_decode);
		context->quantization_decode(buffer, quantization_values);
	PROFILER_EXIT(context->priv->prof_rfx_quantization_decode);

	PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode);
		context->dwt_2d_decode(buffer, dwt_buffer);
	PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode);

	PROFILER_EXIT(context->priv->prof_rfx_decode_component);

	BufferPool_Return(context->priv->BufferPool, dwt_buffer);
}
Пример #3
0
/* stride is bytes between rows in the output buffer. */
BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride)
{
	INT16* pSrcDst[3];
	UINT32 *y_quants, *cb_quants, *cr_quants;
	static const prim_size_t roi_64x64 = { 64, 64 };
	const primitives_t *prims = primitives_get();

	PROFILER_ENTER(context->priv->prof_rfx_decode_rgb);

	y_quants = context->quants + (tile->quantIdxY * 10);
	cb_quants = context->quants + (tile->quantIdxCb * 10);
	cr_quants = context->quants + (tile->quantIdxCr * 10);

	pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */
	pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */
	pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */

	rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */

	rfx_decode_component(context, cb_quants, tile->CbData, tile->CbLen, pSrcDst[1]); /* CbData */

	rfx_decode_component(context, cr_quants, tile->CrData, tile->CrLen, pSrcDst[2]); /* CrData */

	PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb);
	prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16),
			pSrcDst, 64 * sizeof(INT16), &roi_64x64);
	PROFILER_EXIT(context->priv->prof_rfx_ycbcr_to_rgb);

	PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb);
		rfx_decode_format_rgb(pSrcDst[0], pSrcDst[1], pSrcDst[2],
			context->pixel_format, rgb_buffer, stride);
	PROFILER_EXIT(context->priv->prof_rfx_decode_format_rgb);
	
	PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);

	BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16);
	BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16);
	BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16);

	return TRUE;
}
Пример #4
0
static void rfx_decode_component(RFX_CONTEXT* context, const uint32* quantization_values,
	const uint8* data, int size, sint16* buffer)
{
	PROFILER_ENTER(context->priv->prof_rfx_decode_component);

	PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode);
		rfx_rlgr_decode(context->mode, data, size, buffer, 4096);
	PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode);

	PROFILER_ENTER(context->priv->prof_rfx_differential_decode);
		rfx_differential_decode(buffer + 4032, 64);
	PROFILER_EXIT(context->priv->prof_rfx_differential_decode);

	PROFILER_ENTER(context->priv->prof_rfx_quantization_decode);
		context->quantization_decode(buffer, quantization_values);
	PROFILER_EXIT(context->priv->prof_rfx_quantization_decode);

	PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode);
		context->dwt_2d_decode(buffer, context->priv->dwt_buffer);
	PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode);

	PROFILER_EXIT(context->priv->prof_rfx_decode_component);
}
Пример #5
0
void ChessBoard::MakeBlackMove (
    Move         &move,
    UnmoveInfo   &unmove,
    bool      look_for_self_check,
    bool      look_for_enemy_check )
{
    PROFILER_ENTER(PX_MAKEMOVE);

    int dest   = move.dest;
    int source = (move.source & BOARD_OFFSET_MASK);

#if CHESS_MOVE_DEBUG
    if ( source < OFFSET(2,2) || source > OFFSET(9,9) || (board[source] & OFFBOARD) )
        ChessFatal ( "Invalid source in ChessBoard::MakeBlackMove" );

    if ( board[source] == EMPTY )
        ChessFatal ( "Source square is empty in ChessBoard::MakeBlackMove" );
#endif

#if BOARD_HASH_DEBUG
    // Copy an image of the board before the move is made
    SQUARE saveBoardBeforeMove [144];
    for ( int _temp = 0; _temp < 144; ++_temp )
        saveBoardBeforeMove[_temp] = board[_temp];
#endif

    SQUARE capture = EMPTY;
    SQUARE piece = board[source];

#if BOARD_HASH_DEBUG
    if ( !(piece & BLACK_MASK) )
    {
        DebugDumpBoard ( board, "attempt to move non-black piece in MakeBlackMove", move );
        ChessFatal ( "Attempt to move non-black piece in MakeBlackMove" );
    }
#endif

    unmove.flags           =   flags;
    unmove.bmaterial       =   bmaterial;
    unmove.wmaterial       =   wmaterial;
    unmove.prev_move       =   prev_move;
    unmove.lastCapOrPawn   =   lastCapOrPawn;
    unmove.cachedHash      =   cachedHash;

    if ( dest > OFFSET(9,9) )
    {
        // If we get here, it means that this is a "special" move.
        // Special moves store a move code in 'dest', instead of the
        // actual board offset of the move's destination.
        // The move's actual destination is calculated based on
        // what kind of special move this is.

        switch ( dest & SPECIAL_MOVE_MASK )      // Get kind of special move from 'dest'
        {
        case SPECIAL_MOVE_PROMOTE_NORM:
            piece = PROM_PIECE ( dest, BLACK_IND );
            --inventory [BP_INDEX];
            ++inventory [SPIECE_INDEX(piece)];
            bmaterial += (RAW_PIECE_VALUE(piece) - PAWN_VAL);
            LIFT_PIECE(board[source],source);
            board [source] = EMPTY;
            board [dest = source + SOUTH] = piece;
            DROP_PIECE(piece,dest);
            lastCapOrPawn = ply_number;
            break;

        case SPECIAL_MOVE_PROMOTE_CAP_EAST:
            capture = board [source + SOUTHEAST];
            LIFT_PIECE(capture, source + SOUTHEAST);
            piece = PROM_PIECE ( dest, BLACK_IND );
            --inventory [BP_INDEX];    // promoted pawn "disappears"
            ++inventory [SPIECE_INDEX(piece)];   // prom piece "created"
            bmaterial += (RAW_PIECE_VALUE(piece) - PAWN_VAL);
            LIFT_PIECE(board[source],source);
            board [source] = EMPTY;
            board [dest = source + SOUTHEAST] = piece;
            DROP_PIECE(piece,dest);
            break;

        case SPECIAL_MOVE_PROMOTE_CAP_WEST:
            capture = board [source + SOUTHWEST];
            LIFT_PIECE(capture, source + SOUTHWEST);
            piece = PROM_PIECE ( dest, BLACK_IND );
            --inventory [BP_INDEX];    // promoted pawn "disappears"
            ++inventory [SPIECE_INDEX(piece)];   // prom piece "created"
            bmaterial += (RAW_PIECE_VALUE(piece) - PAWN_VAL);
            LIFT_PIECE(board[source], source);
            board [source] = EMPTY;
            board [dest = source + SOUTHWEST] = piece;
            DROP_PIECE(piece,dest);
            break;

        case SPECIAL_MOVE_KCASTLE:
            dest = bk_offset = OFFSET(8,9);
            LIFT_PIECE(BKING,OFFSET(6,9));
            DROP_PIECE(BKING,OFFSET(8,9));
            board [OFFSET(6,9)] = EMPTY;
            board [OFFSET(8,9)] = BKING;
            LIFT_PIECE(BROOK,OFFSET(9,9));
            DROP_PIECE(BROOK,OFFSET(7,9));
            board [OFFSET(9,9)] = EMPTY;
            board [OFFSET(7,9)] = BROOK;
            flags |= (SF_BKMOVED | SF_BKRMOVED);
            break;

        case SPECIAL_MOVE_QCASTLE:
            dest = bk_offset = OFFSET(4,9);
            LIFT_PIECE(BKING,OFFSET(6,9));
            DROP_PIECE(BKING,OFFSET(4,9));
            board [OFFSET(6,9)] = EMPTY;
            board [OFFSET(4,9)] = BKING;
            LIFT_PIECE(BROOK,OFFSET(2,9));
            DROP_PIECE(BROOK,OFFSET(5,9));
            board [OFFSET(2,9)] = EMPTY;
            board [OFFSET(5,9)] = BROOK;
            flags |= (SF_BKMOVED | SF_BQRMOVED);
            break;

        case SPECIAL_MOVE_EP_EAST:
            LIFT_PIECE(piece,source);
            board [source] = EMPTY;
            board [dest = source + SOUTHEAST] = piece;
            DROP_PIECE(piece,dest);
            capture = board [source + EAST];
            board [source + EAST] = EMPTY;
            LIFT_PIECE(capture,source + EAST);
            break;

        case SPECIAL_MOVE_EP_WEST:
            LIFT_PIECE(piece,source);
            board [source] = EMPTY;
            board [dest = source + SOUTHWEST] = piece;
            DROP_PIECE(piece,dest);
            capture = board [source + WEST];
            board [source + WEST] = EMPTY;
            LIFT_PIECE(capture,source + WEST);
            break;

        default:
            ChessFatal ( "Invalid special move code in ChessBoard::MakeBlackMove" );
            break;
        }
    }
    else    // This is a "normal" move...
    {
        capture = board[dest];      // Remember what was captured
        if ( capture != EMPTY )
        {
            LIFT_PIECE(capture,dest);

            // look for bugs in move generator...
            if ( capture & (WK_MASK | BLACK_MASK | OFFBOARD) )
            {
                if ( capture & WK_MASK )
                    ChessFatal ( "Attempt to capture white king in ChessBoard::MakeBlackMove" );
                else if ( capture & OFFBOARD )
                    ChessFatal ( "Attempt to move piece off the board in ChessBoard::MakeBlackMove" );
                else
                    ChessFatal ( "Attempt to capture black piece in ChessBoard::MakeBlackMove" );
            }
        }

        LIFT_PIECE(piece,source);   // update hash codes ...
        DROP_PIECE(piece,dest);     // ... due to piece moving

        board[dest]    =  piece;    // Move the piece
        board[source]  =  EMPTY;    // Erase piece from old square

        if ( piece & BK_MASK )
        {
            flags |= SF_BKMOVED;
            bk_offset = dest;
        }
        else
        {
            if ( source == OFFSET(9,9) )
            {
                if ( piece & BR_MASK )
                    flags |= SF_BKRMOVED;
            }
            else if ( source == OFFSET(2,9) )
            {
                if ( piece & BR_MASK )
                    flags |= SF_BQRMOVED;
            }
        }
    }

    if ( (unmove.capture = capture) != EMPTY )
    {
        // Update material, inventory, etc.
        --inventory [SPIECE_INDEX(capture)];    // one less of the captured piece
        wmaterial -= RAW_PIECE_VALUE(capture);  // deduct material from white

        lastCapOrPawn = ply_number;

        // See if we captured a white rook which had not yet moved...
        // If so, we set its "moved" flag, so that the special case
        // of white moving the other rook onto the square later does not
        // confuse the legal move generator into thinking it can castle!
        // This is because the legal move generator simply checks for
        // the flag NOT being set and a white rook in the square.
        // This is safe even if the rook being captured isn't the original,
        // unmoved rook.  In this case, we are setting the flag redundantly.

        if ( dest == OFFSET(9,2) )
        {
            if ( capture & WR_MASK )
                flags |= SF_WKRMOVED;
        }
        else if ( dest == OFFSET(2,2) )
        {
            if ( capture & WR_MASK )
                flags |= SF_WQRMOVED;
        }
    }
    else if ( piece & BP_MASK )  // not a capture, but might be pawn advance
        lastCapOrPawn = ply_number;

    if ( look_for_self_check )
    {
        if ( IsAttackedByWhite(bk_offset) )
            flags |= SF_BCHECK;
        else
            flags &= ~SF_BCHECK;

        if ( look_for_enemy_check )
        {
            if ( IsAttackedByBlack(wk_offset) )
            {
                flags |= SF_WCHECK;
                move.source |= CAUSES_CHECK_BIT;
            }
            else
                flags &= ~SF_WCHECK;
        }
    }
    else
    {
        // If we get here, it means that we are re-making the move
        // on the board with the knowledge that it is a legal move.
        // It also means that the high-order bit of move.source tells
        // whether this move causes check to white.

        flags &= ~(SF_WCHECK | SF_BCHECK);
        if ( move.source & CAUSES_CHECK_BIT )
            flags |= SF_WCHECK;
    }

    if ( ply_number < MAX_GAME_HISTORY )
        gameHistory [ply_number] = move;

    ++ply_number;
    prev_move = move;
    white_to_move = true;

    if ( cachedHash == 0 )
        cachedHash = 0xFFFFFFFF;   // This way we know 0 will never match any hash code

    ++whiteRepeatHash[cachedHash % REPEAT_HASH_SIZE];

#if BOARD_HASH_DEBUG
    UINT32 actualHash = CalcHash();
    if ( cachedHash != actualHash )
    {
        DebugDumpBoard ( saveBoardBeforeMove, "Hash code out of whack - before black move", move );
        DebugDumpBoard ( board, "Hash code out of whack - after black move", move );
        ChessFatal ( "Hash code out of whack in ChessBoard::MakeBlackMove()" );
        cachedHash = actualHash;  // fix it to avoid cascades
    }
#endif

    PROFILER_EXIT()
}
Пример #6
0
/* ------------------------------------------------------------------------- */
static BOOL test_YCoCgRToRGB_8u_AC4R_func(UINT32 width, UINT32 height)
{
	pstatus_t status = -1;
	BYTE* out_sse = NULL;
	BYTE* in = NULL;
	BYTE* out_c = NULL;
	UINT32 i, x;
	const UINT32 srcStride = width * 4;
	const UINT32 size = srcStride * height;
	const UINT32 formats[] =
	{
		PIXEL_FORMAT_ARGB32,
		PIXEL_FORMAT_ABGR32,
		PIXEL_FORMAT_RGBA32,
		PIXEL_FORMAT_RGBX32,
		PIXEL_FORMAT_BGRA32,
		PIXEL_FORMAT_BGRX32
	};
	PROFILER_DEFINE(genericProf);
	PROFILER_DEFINE(optProf);
	in = _aligned_malloc(size, 16);
	out_c = _aligned_malloc(size, 16);
	out_sse = _aligned_malloc(size, 16);

	if (!in || !out_c || !out_sse)
		goto fail;

	winpr_RAND(in, size);

	for (x = 0; x < sizeof(formats) / sizeof(formats[0]); x++)
	{
		const UINT32 format = formats[x];
		const UINT32 dstStride = width * GetBytesPerPixel(format);
		const char* formatName = GetColorFormatName(format);
		PROFILER_CREATE(genericProf, "YCoCgRToRGB_8u_AC4R-GENERIC");
		PROFILER_CREATE(optProf, "YCoCgRToRGB_8u_AC4R-OPT");
		PROFILER_ENTER(genericProf);
		status = generic->YCoCgToRGB_8u_AC4R(
		             in, srcStride,
		             out_c, format, dstStride, width, height, 2, TRUE);
		PROFILER_EXIT(genericProf);

		if (status != PRIMITIVES_SUCCESS)
			goto loop_fail;

		PROFILER_ENTER(optProf);
		status = optimized->YCoCgToRGB_8u_AC4R(
		             in, srcStride,
		             out_sse, format, dstStride, width, height, 2, TRUE);
		PROFILER_EXIT(optProf);

		if (status != PRIMITIVES_SUCCESS)
			goto loop_fail;

		if (memcmp(out_c, out_sse, dstStride * height) != 0)
		{
			for (i = 0; i < width * height; ++i)
			{
				const UINT32 c = ReadColor(out_c + 4 * i, format);
				const UINT32 sse = ReadColor(out_sse + 4 * i, format);

				if (c != sse)
				{
					printf("optimized->YCoCgRToRGB FAIL[%s] [%"PRIu32"]: 0x%08"PRIx32" -> C 0x%08"PRIx32" vs optimized 0x%08"PRIx32"\n",
					       formatName, i, in[i + 1], c, sse);
					status = -1;
				}
			}
		}

		printf("--------------------------- [%s] [%"PRIu32"x%"PRIu32"] ---------------------------\n",
		       formatName, width, height);
		PROFILER_PRINT_HEADER;
		PROFILER_PRINT(genericProf);
		PROFILER_PRINT(optProf);
		PROFILER_PRINT_FOOTER;
	loop_fail:
		PROFILER_FREE(genericProf);
		PROFILER_FREE(optProf);

		if (status != PRIMITIVES_SUCCESS)
			goto fail;
	}

fail:
	_aligned_free(in);
	_aligned_free(out_c);
	_aligned_free(out_sse);
	return status == PRIMITIVES_SUCCESS;
}
Пример #7
0
/* stride is bytes between rows in the output buffer. */
BOOL rfx_decode_rgb(RFX_CONTEXT* context, wStream* data_in,
	int y_size, const UINT32* y_quants,
	int cb_size, const UINT32* cb_quants,
	int cr_size, const UINT32* cr_quants, BYTE* rgb_buffer, int stride)
{
	INT16* pSrcDst[3];
	static const prim_size_t roi_64x64 = { 64, 64 };
	const primitives_t *prims = primitives_get();

	PROFILER_ENTER(context->priv->prof_rfx_decode_rgb);

	pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */
	pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */
	pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */

#if 0
	if (context->priv->UseThreads)
	{
		PTP_WORK work_objects[3];
		RFX_COMPONENT_WORK_PARAM params[3];

		params[0].context = context;
		params[0].quantization_values = y_quants;
		params[0].buffer = stream_get_tail(data_in);
		params[0].capacity = y_size;
		params[0].buffer = pSrcDst[0];
		stream_seek(data_in, y_size);

		params[1].context = context;
		params[1].quantization_values = cb_quants;
		params[1].buffer = stream_get_tail(data_in);
		params[1].capacity = cb_size;
		params[1].buffer = pSrcDst[1];
		stream_seek(data_in, cb_size);

		params[2].context = context;
		params[2].quantization_values = cr_quants;
		params[2].buffer = stream_get_tail(data_in);
		params[2].capacity = cr_size;
		params[2].buffer = pSrcDst[2];
		stream_seek(data_in, cr_size);

		work_objects[0] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_decode_component_work_callback,
				(void*) &params[0], &context->priv->ThreadPoolEnv);
		work_objects[1] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_decode_component_work_callback,
				(void*) &params[1], &context->priv->ThreadPoolEnv);
		work_objects[2] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_decode_component_work_callback,
				(void*) &params[2], &context->priv->ThreadPoolEnv);

		SubmitThreadpoolWork(work_objects[0]);
		SubmitThreadpoolWork(work_objects[1]);
		SubmitThreadpoolWork(work_objects[2]);

		WaitForThreadpoolWorkCallbacks(work_objects[0], FALSE);
		WaitForThreadpoolWorkCallbacks(work_objects[1], FALSE);
		WaitForThreadpoolWorkCallbacks(work_objects[2], FALSE);
	}
	else
#endif
	{
		if (stream_get_left(data_in) < y_size+cb_size+cr_size)
		{
			DEBUG_WARN("rfx_decode_rgb: packet too small for y_size+cb_size+cr_size");
			return FALSE;
		}
		rfx_decode_component(context, y_quants, stream_get_tail(data_in), y_size, pSrcDst[0]); /* YData */
		stream_seek(data_in, y_size);

		rfx_decode_component(context, cb_quants, stream_get_tail(data_in), cb_size, pSrcDst[1]); /* CbData */
		stream_seek(data_in, cb_size);

		rfx_decode_component(context, cr_quants, stream_get_tail(data_in), cr_size, pSrcDst[2]); /* CrData */
		stream_seek(data_in, cr_size);
	}

	prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16),
			pSrcDst, 64 * sizeof(INT16), &roi_64x64);

	PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb);
		rfx_decode_format_rgb(pSrcDst[0], pSrcDst[1], pSrcDst[2],
			context->pixel_format, rgb_buffer, stride);
	PROFILER_EXIT(context->priv->prof_rfx_decode_format_rgb);
	
	PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);

	BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16);
	BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16);
	BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16);
	return TRUE;
}