<commit_before>//
// Created by main on 20.09.2015.
//

#include "AST.h"
#include "Error.h"
#include "FunctionNameMangler.h"
#include "BuiltinFunctions.h"
#include <set>

namespace Helen
{
unique_ptr<Module> AST::module = 0;
unique_ptr<legacy::FunctionPassManager> AST::fpm = 0;
IRBuilder<> AST::builder(getGlobalContext());
map<string, AllocaInst*> AST::variables;
map<string, Function*> AST::functions;
map<string, Type*> AST::types;
map<string, vector<string> > AST::fields;
stack<string> AST::callstack;

AllocaInst* AST::createEntryBlockAlloca(Function* f, Type* t, const std::string& VarName)
{
    IRBuilder<> tmp(&f->getEntryBlock(), f->getEntryBlock().begin());
    return tmp.CreateAlloca(t, 0, VarName.c_str());
}

Value* ConstantIntAST::codegen()
{
    return ConstantInt::get(IntegerType::get(getGlobalContext(), bitwidth), value);
}

Value* ConstantRealAST::codegen()
{
    return ConstantFP::get(getGlobalContext(), APFloat(value));
}

Value* ConstantCharAST::codegen()
{
    return ConstantInt::get(Type::getInt8Ty(getGlobalContext()), value);
}

Value* ConstantStringAST::codegen()
{
    return ConstantDataArray::getString(getGlobalContext(), StringRef(value)); // TODO: String
}

Value* DeclarationAST::codegen()
{
    Function* f = builder.GetInsertBlock()->getParent();

    Value* initValue;
    if (initialiser) {
        initValue = initialiser->codegen();
        if (!initValue)
            return nullptr;
    } else {
        initValue = Constant::getNullValue(type);
    }
    AllocaInst* alloca = createEntryBlockAlloca(f, type, name);
    if (initValue)
        builder.CreateStore(initValue, alloca);
    variables[name] = alloca;
}

Value* VariableAST::codegen()
{
    try
    {
        Value* val = variables.at(name);
        return builder.CreateLoad(val, name.c_str());
    }
    catch (out_of_range)
    {
        return Error::errorValue(ErrorType::UndeclaredVariable, { name });
    }
}

Value* ConditionAST::codegen()
{
    Value* cond = condition->codegen();
    if (!cond)
        return 0;
    cond = builder.CreateICmpNE(cond, ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 0), "ifcond");
    Function* f = builder.GetInsertBlock()->getParent();
    BasicBlock* thenBB = BasicBlock::Create(getGlobalContext(), "then", f);
    BasicBlock* elseBB = BasicBlock::Create(getGlobalContext(), "else");
    BasicBlock* mergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");

    builder.CreateCondBr(cond, thenBB, elseBB);
    // Emit then value.
    builder.SetInsertPoint(thenBB);

    Value* thenValue = thenBranch->codegen();
    if (!thenValue)
        return 0;

    builder.CreateBr(mergeBB);
    thenBB = builder.GetInsertBlock();

    f->getBasicBlockList().push_back(elseBB);
    builder.SetInsertPoint(elseBB);

    Value* elseValue = elseBranch->codegen();
    if (!elseValue)
        return 0;

    builder.CreateBr(mergeBB);
    elseBB = builder.GetInsertBlock();

    f->getBasicBlockList().push_back(mergeBB);
    builder.SetInsertPoint(mergeBB);
    PHINode* PN = builder.CreatePHI(Type::getInt64Ty(getGlobalContext()), 2, "iftmp");

    PN->addIncoming(thenValue, thenBB);
    PN->addIncoming(elseValue, elseBB);
    return PN;
}

Value* FunctionCallAST::codegen()
{
    // Assignment is the special case
    if (functionName == BuiltinFunctions::operatorMarker + "=") {
        shared_ptr<AST> left = arguments[0], right = arguments[1];
        VariableAST* lefte = dynamic_cast<VariableAST*>(left.get());
        if (!lefte)
            return Error::errorValue(ErrorType::AssignmentError, { std::to_string((size_t)lefte) });
        Value* v = right->codegen();
        if (!v)
            return nullptr;
        try
        {
            Value* var = variables.at(lefte->getName());
            builder.CreateStore(v, var);
            return v;
        }
        catch (out_of_range)
        {
            return Error::errorValue(ErrorType::UndeclaredVariable, { lefte->getName() });
        }
    }
    // Index (temporary, should be in BuiltFunction::createIndex)
    if (functionName == "__index") {
        Value* left = arguments[0]->codegen();
        if (left->getType()->isVectorTy()) {
            Value* right = arguments[1]->codegen();
            if (!right->getType()->isIntegerTy(64))
                return Error::errorValue(ErrorType::WrongArgumentType, { "must be int" });
            Constant* one = ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 1);
            right = builder.CreateSub(right, one);
            return builder.CreateExtractElement(left, right, "indtmp");

        } else if (left->getType()->isStructTy()) {
            if (!dynamic_cast<VariableAST*>(arguments[1].get()))
                return Error::errorValue(ErrorType::WrongArgumentType, { "must be ID" });
            string name = ((VariableAST*)arguments[1].get())->getName();
            vector<string> fie = fields[static_cast<StructType*>(left->getType())->getName()];
            auto field = std::find(fie.begin(), fie.end(), name);
            if (field == fie.end()) {
                return Error::errorValue(ErrorType::UndeclaredVariable, { name });
            }
            int pos = field - fie.begin();
            Value* zero = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0);
            Value* ind = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), pos);
            Value* right[] = { zero, ind };
            return builder.CreateGEP(left, right, "indtmp");
        } else {
            return Error::errorValue(ErrorType::IndexArgumentError);
        }
    }
    std::vector<Value*> vargs;
    std::vector<Type*> types;
    for (unsigned i = 0, e = arguments.size(); i != e; ++i) {
        // TODO: add type checking
        vargs.push_back(arguments[i]->codegen());
        if (!vargs.back())
            return nullptr;
    }
    for (Value* v : vargs)
        types.push_back(v->getType());
    // try to find mangled function, then unmangled one
    Function* f = 0;
    string oldFName = functionName;
    for (string style : { "Helen", "C" }) {
        functionName = FunctionNameMangler::mangleName(oldFName, types, style);
        f = module->getFunction(functionName);
        if (f)
            break;
    }
    string hrName = FunctionNameMangler::humanReadableName(functionName);
    if (!f)
        return Error::errorValue(ErrorType::UndeclaredFunction, { hrName, functionName });
    ArrayRef<Type*> params = f->getFunctionType()->params();
    for (unsigned i = 0; i < vargs.size(); i++)
        if (vargs[i]->getType() != params[i])
            return Error::errorValue(ErrorType::WrongArgumentType, { std::to_string(i) });
    return builder.CreateCall(f, vargs, "calltmp");
}

Value* SequenceAST::codegen()
{
    for (shared_ptr<Helen::AST>& a : instructions) {
        Value* v = a->codegen();
        if (dynamic_cast<ReturnAST*>(a.get()))
            return v;
    }
    return 0;
}

Value* NullAST::codegen()
{
    return 0;
}

Function* FunctionPrototypeAST::codegen()
{
    set<string> styles = { "C", "Helen" };
    if (!styles.count(style))
        return (Function*)Error::errorValue(ErrorType::UnknownStyle);
    FunctionType* ft = FunctionType::get(returnType, args, false);
    name = FunctionNameMangler::mangleName(name, args, style);
    Function* f = Function::Create(ft, Function::ExternalLinkage, name, module.get());
    functions[name] = f;

    unsigned i = 0;
    for (auto& arg : f->args()) {
        arg.setName(argNames[i++]);
    }
    return f;
}

Function* FunctionAST::codegen()
{
    Function* f = module->getFunction(proto->getName());

    if (!f)
        f = proto->codegen();

    if (!f)
        return 0;

    if (!f->empty())
        return (Function*)Error::errorValue(ErrorType::FunctionRedefined, { proto->getName() });
    // callstack.push(proto->getName());
    BasicBlock* parent = builder.GetInsertBlock();
    BasicBlock* bb = BasicBlock::Create(getGlobalContext(), "entry", f);
    builder.SetInsertPoint(bb);
    for (auto& arg : f->args()) {
        AllocaInst* alloca = createEntryBlockAlloca(f, arg.getType(), arg.getName());
        builder.CreateStore(&arg, alloca);
        variables[arg.getName()] = alloca;
    }
    if (Value* ret = body->codegen()) {
        builder.CreateRet(ret);
        verifyFunction(*f);
        fpm->run(*f);
        //        callstack.pop();
        //        string previous = callstack.empty() ? "main" : callstack.top();
        //        BasicBlock* bb = BasicBlock::Create(getGlobalContext(), "resume", module->getFunction(previous));
        //        builder.SetInsertPoint(bb);
        builder.SetInsertPoint(parent);
        return f;
    }
    /*callstack.pop();
    string previous = callstack.empty() ? "_main_v" : callstack.top();
    bb = BasicBlock::Create(getGlobalContext(), "resume", module->getFunction(previous));
    builder.SetInsertPoint(bb);*/
    f->eraseFromParent();
    builder.SetInsertPoint(parent);
    return nullptr;
}
Value* ReturnAST::codegen()
{
    Value* ret = result->codegen();
    // builder.CreateRet(ret);
    return ret;
}
Value* CustomTypeAST::codegen()
{
    return 0;
}
void CustomTypeAST::compileTime()
{

    std::vector<string> fieldNames;
    std::vector<Type*> fieldTypes;
    for (shared_ptr<AST> i : instructions) {
        if (dynamic_cast<DeclarationAST*>(i.get())) {
            DeclarationAST* di = (DeclarationAST*)i.get();
            fieldNames.push_back(di->getName());
            fieldTypes.push_back(di->getType());
        }
    }
    fields[typeName] = fieldNames;
    types[typeName] = StructType::create(ArrayRef<Type*>(fieldTypes), typeName);
}
}
<commit_msg>fixed dealing with struct types<commit_after>//
// Created by main on 20.09.2015.
//

#include "AST.h"
#include "Error.h"
#include "FunctionNameMangler.h"
#include "BuiltinFunctions.h"
#include <set>

namespace Helen
{
unique_ptr<Module> AST::module = 0;
unique_ptr<legacy::FunctionPassManager> AST::fpm = 0;
IRBuilder<> AST::builder(getGlobalContext());
map<string, AllocaInst*> AST::variables;
map<string, Function*> AST::functions;
map<string, Type*> AST::types;
map<string, vector<string> > AST::fields;
stack<string> AST::callstack;

AllocaInst* AST::createEntryBlockAlloca(Function* f, Type* t, const std::string& VarName)
{
    IRBuilder<> tmp(&f->getEntryBlock(), f->getEntryBlock().begin());
    return tmp.CreateAlloca(t, 0, VarName.c_str());
}

Value* ConstantIntAST::codegen()
{
    return ConstantInt::get(IntegerType::get(getGlobalContext(), bitwidth), value);
}

Value* ConstantRealAST::codegen()
{
    return ConstantFP::get(getGlobalContext(), APFloat(value));
}

Value* ConstantCharAST::codegen()
{
    return ConstantInt::get(Type::getInt8Ty(getGlobalContext()), value);
}

Value* ConstantStringAST::codegen()
{
    return ConstantDataArray::getString(getGlobalContext(), StringRef(value)); // TODO: String
}

Value* DeclarationAST::codegen()
{
    Function* f = builder.GetInsertBlock()->getParent();

    Value* initValue;
    if (initialiser) {
        initValue = initialiser->codegen();
        if (!initValue)
            return nullptr;
    } else {
        initValue = Constant::getNullValue(type);
    }
    AllocaInst* alloca = createEntryBlockAlloca(f, type, name);
    if (initValue)
        builder.CreateStore(initValue, alloca);
    variables[name] = alloca;
}

Value* VariableAST::codegen()
{
    try
    {
        Value* val = variables.at(name);
        return builder.CreateLoad(val, name.c_str());
    }
    catch (out_of_range)
    {
        return Error::errorValue(ErrorType::UndeclaredVariable, { name });
    }
}

Value* ConditionAST::codegen()
{
    Value* cond = condition->codegen();
    if (!cond)
        return 0;
    cond = builder.CreateICmpNE(cond, ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 0), "ifcond");
    Function* f = builder.GetInsertBlock()->getParent();
    BasicBlock* thenBB = BasicBlock::Create(getGlobalContext(), "then", f);
    BasicBlock* elseBB = BasicBlock::Create(getGlobalContext(), "else");
    BasicBlock* mergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");

    builder.CreateCondBr(cond, thenBB, elseBB);
    // Emit then value.
    builder.SetInsertPoint(thenBB);

    Value* thenValue = thenBranch->codegen();
    if (!thenValue)
        return 0;

    builder.CreateBr(mergeBB);
    thenBB = builder.GetInsertBlock();

    f->getBasicBlockList().push_back(elseBB);
    builder.SetInsertPoint(elseBB);

    Value* elseValue = elseBranch->codegen();
    if (!elseValue)
        return 0;

    builder.CreateBr(mergeBB);
    elseBB = builder.GetInsertBlock();

    f->getBasicBlockList().push_back(mergeBB);
    builder.SetInsertPoint(mergeBB);
    PHINode* PN = builder.CreatePHI(Type::getInt64Ty(getGlobalContext()), 2, "iftmp");

    PN->addIncoming(thenValue, thenBB);
    PN->addIncoming(elseValue, elseBB);
    return PN;
}

Value* FunctionCallAST::codegen()
{
    // Assignment is the special case
    if (functionName == BuiltinFunctions::operatorMarker + "=") {
        shared_ptr<AST> left = arguments[0], right = arguments[1];
        VariableAST* lefte = dynamic_cast<VariableAST*>(left.get());
        if (!lefte)
            return Error::errorValue(ErrorType::AssignmentError, { std::to_string((size_t)lefte) });
        Value* v = right->codegen();
        if (!v)
            return nullptr;
        try
        {
            Value* var = variables.at(lefte->getName());
            builder.CreateStore(v, var);
            return v;
        }
        catch (out_of_range)
        {
            return Error::errorValue(ErrorType::UndeclaredVariable, { lefte->getName() });
        }
    }
    // Index (temporary, should be in BuiltFunction::createIndex)
    if (functionName == "__index") {
        Value* left = arguments[0]->codegen();
        if (left->getType()->isVectorTy()) {
            Value* right = arguments[1]->codegen();
            if (!right->getType()->isIntegerTy(64))
                return Error::errorValue(ErrorType::WrongArgumentType, { "must be int" });
            Constant* one = ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 1);
            right = builder.CreateSub(right, one);
            return builder.CreateExtractElement(left, right, "indtmp");

        } else if (left->getType()->isStructTy()) {
            if (!dynamic_cast<VariableAST*>(arguments[1].get()))
                return Error::errorValue(ErrorType::WrongArgumentType, { "must be ID" });
            string name = ((VariableAST*)arguments[1].get())->getName();
            vector<string> fie = fields[static_cast<StructType*>(left->getType())->getName()];
            auto field = std::find(fie.begin(), fie.end(), name);
            if (field == fie.end()) {
                return Error::errorValue(ErrorType::UndeclaredVariable, { name });
            }
            int pos = field - fie.begin();
            Value* zero = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0);
            Value* ind = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), pos);
            Value* right[] = { zero, ind };
            AllocaInst* aleft = builder.CreateAlloca(left->getType(), 0, "atmp");
            builder.CreateStore(left, aleft);
            Value* tmpptr = builder.CreateInBoundsGEP(aleft, right, "indtmpptr");
            return builder.CreateLoad(tmpptr, "indtmp");
        } else {
            return Error::errorValue(ErrorType::IndexArgumentError);
        }
    }
    std::vector<Value*> vargs;
    std::vector<Type*> types;
    for (unsigned i = 0, e = arguments.size(); i != e; ++i) {
        // TODO: add type checking
        vargs.push_back(arguments[i]->codegen());
        if (!vargs.back())
            return nullptr;
    }
    for (Value* v : vargs)
        types.push_back(v->getType());
    // try to find mangled function, then unmangled one
    Function* f = 0;
    string oldFName = functionName;
    for (string style : { "Helen", "C" }) {
        functionName = FunctionNameMangler::mangleName(oldFName, types, style);
        f = module->getFunction(functionName);
        if (f)
            break;
    }
    string hrName = FunctionNameMangler::humanReadableName(functionName);
    if (!f)
        return Error::errorValue(ErrorType::UndeclaredFunction, { hrName, functionName });
    ArrayRef<Type*> params = f->getFunctionType()->params();
    for (unsigned i = 0; i < vargs.size(); i++)
        if (vargs[i]->getType() != params[i])
            return Error::errorValue(ErrorType::WrongArgumentType, { std::to_string(i) });
    return builder.CreateCall(f, vargs, "calltmp");
}

Value* SequenceAST::codegen()
{
    for (shared_ptr<Helen::AST>& a : instructions) {
        Value* v = a->codegen();
        if (dynamic_cast<ReturnAST*>(a.get()))
            return v;
    }
    return 0;
}

Value* NullAST::codegen()
{
    return 0;
}

Function* FunctionPrototypeAST::codegen()
{
    set<string> styles = { "C", "Helen" };
    if (!styles.count(style))
        return (Function*)Error::errorValue(ErrorType::UnknownStyle);
    FunctionType* ft = FunctionType::get(returnType, args, false);
    name = FunctionNameMangler::mangleName(name, args, style);
    Function* f = Function::Create(ft, Function::ExternalLinkage, name, module.get());
    functions[name] = f;

    unsigned i = 0;
    for (auto& arg : f->args()) {
        arg.setName(argNames[i++]);
    }
    return f;
}

Function* FunctionAST::codegen()
{
    Function* f = module->getFunction(proto->getName());

    if (!f)
        f = proto->codegen();

    if (!f)
        return 0;

    if (!f->empty())
        return (Function*)Error::errorValue(ErrorType::FunctionRedefined, { proto->getName() });
    // callstack.push(proto->getName());
    BasicBlock* parent = builder.GetInsertBlock();
    BasicBlock* bb = BasicBlock::Create(getGlobalContext(), "entry", f);
    builder.SetInsertPoint(bb);
    for (auto& arg : f->args()) {
        AllocaInst* alloca = createEntryBlockAlloca(f, arg.getType(), arg.getName());
        builder.CreateStore(&arg, alloca);
        variables[arg.getName()] = alloca;
    }
    if (Value* ret = body->codegen()) {
        builder.CreateRet(ret);
        verifyFunction(*f);
        fpm->run(*f);
        //        callstack.pop();
        //        string previous = callstack.empty() ? "main" : callstack.top();
        //        BasicBlock* bb = BasicBlock::Create(getGlobalContext(), "resume", module->getFunction(previous));
        //        builder.SetInsertPoint(bb);
        builder.SetInsertPoint(parent);
        return f;
    }
    /*callstack.pop();
    string previous = callstack.empty() ? "_main_v" : callstack.top();
    bb = BasicBlock::Create(getGlobalContext(), "resume", module->getFunction(previous));
    builder.SetInsertPoint(bb);*/
    f->eraseFromParent();
    builder.SetInsertPoint(parent);
    return nullptr;
}
Value* ReturnAST::codegen()
{
    Value* ret = result->codegen();
    // builder.CreateRet(ret);
    return ret;
}
Value* CustomTypeAST::codegen()
{
    return 0;
}
void CustomTypeAST::compileTime()
{

    std::vector<string> fieldNames;
    std::vector<Type*> fieldTypes;
    for (shared_ptr<AST> i : instructions) {
        if (dynamic_cast<DeclarationAST*>(i.get())) {
            DeclarationAST* di = (DeclarationAST*)i.get();
            fieldNames.push_back(di->getName());
            fieldTypes.push_back(di->getType());
        }
    }
    fields[typeName] = fieldNames;
    types[typeName] = StructType::create(ArrayRef<Type*>(fieldTypes), typeName);
}
}
<|endoftext|>


<commit_before>#include <possumwood_sdk/node_implementation.h>

#include <actions/traits.h>

#include "possumwood_sdk/datatypes/enum.h"

#include "tools.h"
#include "frame.h"

namespace {

static const std::vector<std::pair<std::string, int>> s_modes {{
	std::pair<std::string, int>("Min-max", cv::NORM_MINMAX),
	std::pair<std::string, int>("Infinity norm", cv::NORM_INF),
	std::pair<std::string, int>("L1 norm", cv::NORM_L1),
	std::pair<std::string, int>("L2 norm", cv::NORM_L2),
	std::pair<std::string, int>("L2 square norm", cv::NORM_L2SQR),
	std::pair<std::string, int>("Hamming", cv::NORM_HAMMING),
	std::pair<std::string, int>("Hamming squared", cv::NORM_HAMMING2),
}};

dependency_graph::InAttr<possumwood::opencv::Frame> a_in;
dependency_graph::InAttr<possumwood::Enum> a_mode;
dependency_graph::OutAttr<possumwood::opencv::Frame> a_out;

dependency_graph::State compute(dependency_graph::Values& data) {
	cv::Mat result;
	cv::normalize(*data.get(a_in), result, 1, 0, data.get(a_mode).intValue());

	data.set(a_out, possumwood::opencv::Frame(result));

	return dependency_graph::State();
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_in, "in_frame", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);
	meta.addAttribute(a_mode, "mode", possumwood::Enum(s_modes.begin(), s_modes.end()));
	meta.addAttribute(a_out, "out_frame", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);

	meta.addInfluence(a_in, a_out);
	meta.addInfluence(a_mode, a_out);

	meta.setCompute(compute);
}

possumwood::NodeImplementation s_impl("opencv/normalize", init);

}
<commit_msg>Reimplemented image normalization - OpenCV version is behaving strangely<commit_after>#include <possumwood_sdk/node_implementation.h>

#include <actions/traits.h>

#include "possumwood_sdk/datatypes/enum.h"

#include "tools.h"
#include "frame.h"

namespace {

dependency_graph::InAttr<possumwood::opencv::Frame> a_in;
dependency_graph::InAttr<possumwood::Enum> a_mode;
dependency_graph::OutAttr<possumwood::opencv::Frame> a_out;

dependency_graph::State compute(dependency_graph::Values& data) {
	cv::Mat m = *data.get(a_in).clone();

	if(m.rows > 0 && m.cols > 0) {
		if(data.get(a_mode).value() == "Min-max") {
			float min = m.at<float>(0,0);
			float max = m.at<float>(0,0);

			for(int y=0;y<m.rows;++y)
				for(int x=0;x<m.cols;++x) {
					const float current = m.at<float>(y, x);
					min = std::min(min, current);
					max = std::max(max, current);
				}

			for(int y=0;y<m.rows;++y)
				for(int x=0;x<m.cols;++x) {
					float& current = m.at<float>(y, x);
					current = (current - min) / (max - min);
				}
		}

		else if(data.get(a_mode).value() == "Max") {
			float max = m.at<float>(0,0);

			for(int y=0;y<m.rows;++y)
				for(int x=0;x<m.cols;++x) {
					const float current = m.at<float>(y, x);
					max = std::max(max, current);
				}

			for(int y=0;y<m.rows;++y)
				for(int x=0;x<m.cols;++x) {
					float& current = m.at<float>(y, x);
					current = current / max;
				}
		}
	}

	data.set(a_out, possumwood::opencv::Frame(m));

	return dependency_graph::State();
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_in, "in_frame", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);
	meta.addAttribute(a_mode, "mode", possumwood::Enum({"Min-max", "Max"}));
	meta.addAttribute(a_out, "out_frame", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);

	meta.addInfluence(a_in, a_out);
	meta.addInfluence(a_mode, a_out);

	meta.setCompute(compute);
}

possumwood::NodeImplementation s_impl("opencv/normalize", init);

}
<|endoftext|>


<commit_before>//**************************************************************
//*            OpenGLide - Glide to OpenGL Wrapper
//*             http://openglide.sourceforge.net
//*
//*               Linear Frame Buffer Functions
//*
//*         OpenGLide is OpenSource under LGPL license
//*              Originaly made by Fabio Barros
//*      Modified by Paul for Glidos (http://www.glidos.net)
//**************************************************************

#include "GlOgl.h"
#include "Glextensions.h"
#include "GLRender.h"

#define BLUE_SCREEN (0x7ff)

inline void Convert565to8888( WORD *Buffer1, DWORD *Buffer2, DWORD Pixels )
{
    while ( Pixels )
    {
        *Buffer2++ = ( (*Buffer1) ? 0xFF000000 : 0x00000000 ) |   // A
                     ( (*Buffer1)     & 0x001F) << 19 |           // B
                     ( (*Buffer1)     & 0x07E0) << 5  |           // G
                     ( (*Buffer1++)   & 0xF800) >> 8;             // R
        Pixels--;
    }
}

inline void Convert565to5551( WORD *Buffer1, WORD *Buffer2, DWORD Pixels )
{
    while ( Pixels )
    {
        *Buffer2++ = ((*Buffer1) & 0xFFC0) |
                    (((*Buffer1) & 0x001F) << 1) |
                    ( (*Buffer1++) ? 0x0001 : 0x0000);
        Pixels--;
    }
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbLock( GrLock_t dwType,
           GrBuffer_t dwBuffer,
           GrLfbWriteMode_t dwWriteMode,
           GrOriginLocation_t dwOrigin,
           FxBool bPixelPipeline,
           GrLfbInfo_t *lfbInfo )
{
#ifdef CRITICAL
    GlideMsg("grLfbLock( %d, %d, %d, %d, %d, --- )\n", dwType, dwBuffer, dwWriteMode, dwOrigin, bPixelPipeline);
#endif

    int width = Glide.WindowWidth;
    int height = Glide.WindowHeight;

    RenderDrawTriangles( );

    if ( ( dwType & 1) == 0 )
    {
        FxU32 *buf = new FxU32[ width * height ];
        int i,
            j;

        glReadBuffer( dwBuffer == GR_BUFFER_BACKBUFFER
                      ? GL_BACK : GL_FRONT );

        glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void *)buf );

        for ( j = 0; j < height; j++ )
        {
            WORD    * line = Glide.SrcBuffer.Address + ( height - 1 - j ) * width;
            FxU32   * bufl = buf + j * width;

            for ( i = 0; i < width; i++ )
            {
                line[ i ] = (WORD)
                    ( ( ( bufl[i] & 0xf8 )     << 8 )
                    | ( ( bufl[i] & 0xfc00 )   >> 5 )
                    | ( ( bufl[i] & 0xf80000 ) >> 19 )
                    );
            }
        }

        delete[] buf;

        Glide.SrcBuffer.Lock = true;
        Glide.SrcBuffer.Type = dwType;
        Glide.SrcBuffer.Buffer = dwBuffer;
        Glide.SrcBuffer.WriteMode = dwWriteMode;

        lfbInfo->lfbPtr = Glide.SrcBuffer.Address;
    }
    else
    {
        for ( int i = 0; i < width * height; i++ )
        {
            Glide.DstBuffer.Address[ i ] = BLUE_SCREEN;
        }

        Glide.DstBuffer.Lock = true;
        Glide.DstBuffer.Type = dwType;
        Glide.DstBuffer.Buffer = dwBuffer;
        Glide.DstBuffer.WriteMode = dwWriteMode;

        lfbInfo->lfbPtr = Glide.DstBuffer.Address;
    }

    lfbInfo->strideInBytes = Glide.WindowWidth * 2;

    lfbInfo->writeMode = GR_LFBWRITEMODE_565;

    return FXTRUE;
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbUnlock( GrLock_t dwType, GrBuffer_t dwBuffer )
{
#ifdef CRITICAL
    GlideMsg("grLfbUnlock( %d, %d )\n", dwType, dwBuffer );
#endif

    int width = Glide.WindowWidth;
    int height = Glide.WindowHeight;

    if ( ( dwType & 1 ) == 0 )
    {
        if ( !Glide.SrcBuffer.Lock )
        {
            return FXFALSE;
        }

        Glide.SrcBuffer.Lock = false;

        return FXTRUE;
    }
    else
    {
        int x,
            y,
            maxx = 0,
            maxy = 0,
            minx = 2048,
            miny = 2048;

        if( !Glide.DstBuffer.Lock )
        {
            return FXFALSE;
        }

        for ( y = 0; y < height; y++ )
        {
            for ( x = 0; x < width; x++ )
            {
                if ( Glide.DstBuffer.Address[ y * width + x ] != BLUE_SCREEN )
                {
                    if ( x > maxx ) maxx = x;
                    if ( y > maxy ) maxy = y;
                    if ( x < minx ) minx = x;
                    if ( y < miny ) miny = y;
                }
            }
        }

        if ( maxx >= minx )
        {
            int xsize = maxx + 1 - minx;
            int ysize = maxy + 1 - miny;
            FxU32 *buf = new FxU32[ xsize * ysize ];

            glReadBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                          ? GL_BACK : GL_FRONT );

            glReadPixels( minx, height - miny-ysize,
                          xsize, ysize,
                          GL_RGBA, GL_UNSIGNED_BYTE, (void *) buf );

            for ( y = 0; y < ysize; y++ )
            {
                WORD    * line = Glide.DstBuffer.Address + ( miny + ysize - 1 - y ) *
                                 width + minx;
                FxU32   * bufl = buf + y * xsize;

                for ( x = 0; x < xsize; x++ )
                {
                    if ( line[ x ] != BLUE_SCREEN )
                    {
                        bufl[ x ] = ( ( (line[x] & 0x001f ) << 19)
                                  |   ( (line[x] & 0x07e0 ) << 5 )
                                  |   ( (line[x] & 0xf100 ) >> 8 )
                                  | 0xff000000);
                    }
                }
            }

            glDisable( GL_BLEND );

            glDisable( GL_TEXTURE_2D );

            glDrawBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                          ? GL_BACK : GL_FRONT );

            glRasterPos2i( minx,  miny + ysize );

            glDrawPixels( xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, (void *) buf );

            glDrawBuffer( OpenGL.RenderBuffer );

            if ( OpenGL.Blend )
            {
                glEnable( GL_BLEND );
            }

            if ( Glide.DstBuffer.Buffer != GR_BUFFER_BACKBUFFER )
            {
                glFlush( );
            }

            delete[] buf;
        }

        Glide.DstBuffer.Lock = false;

        return FXTRUE;
    }
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbReadRegion( GrBuffer_t src_buffer,
                 FxU32 src_x, FxU32 src_y,
                 FxU32 src_width, FxU32 src_height,
                 FxU32 dst_stride, void *dst_data )
{
#ifdef NOTDONE
    GlideMsg("grLfbReadRegion( %d, %d, %d, %d, %d, %d, --- )\n",
        src_buffer, src_x, src_y, src_width, src_height, dst_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD PixelsX, PixelsY;
    static DWORD Stride;

    RenderDrawTriangles( );

    switch ( src_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glReadBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glReadBuffer( GL_BACK );    break;
    }

    glReadPixels( src_x, src_y, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)Glide.SrcBuffer.Address );
//  glReadPixels( 320, 230, 300, 200, GL_RED, GL_UNSIGNED_BYTE, &Glide.SrcBuffer.Address );
//  glDrawPixels( 300, 200, GL_RED , GL_UNSIGNED_BYTE, Glide.SrcBuffer.Address );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbReadRegion" );
#endif

    return FXTRUE;
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbWriteRegion( GrBuffer_t dst_buffer,
                  FxU32 dst_x, FxU32 dst_y,
                  GrLfbSrcFmt_t src_format,
                  FxU32 src_width, FxU32 src_height,
                  FxI32 src_stride, void *src_data )
{
#ifdef NOTDONE
    GlideMsg("grLfbWriteRegion( %d, %d, %d, %d, %d, %d, %d, --- )\n",
        dst_buffer, dst_x, dst_y, src_format, src_width, src_height, src_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD Pixels;

    RenderDrawTriangles( );

    if ( src_stride != (FxI32)src_width )
    {
//      Error( "grLfbWriteRegion: different width and stride.\n" );
        return FXTRUE;
    }

    switch ( dst_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glDrawBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glDrawBuffer( GL_BACK );    break;
    }

    glRasterPos2i( dst_x, dst_y );

    switch ( src_format )
    {
    case GR_LFB_SRC_FMT_565:
    case GR_LFB_SRC_FMT_555:
    case GR_LFB_SRC_FMT_1555:
    case GR_LFB_SRC_FMT_888:
        break;

    case GR_LFB_SRC_FMT_8888:
        break;

    case GR_LFB_SRC_FMT_565_DEPTH:
    case GR_LFB_SRC_FMT_555_DEPTH:
    case GR_LFB_SRC_FMT_1555_DEPTH:
    case GR_LFB_SRC_FMT_ZA16:
    case GR_LFB_SRC_FMT_RLE16:
        break;
    }

//  glDrawPixels( src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, Glide.SrcBuffer.Buffer );

    glDrawBuffer( OpenGL.RenderBuffer );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbWriteRegion" );
#endif

    return FXTRUE;
}

DLLEXPORT void __stdcall
grLfbConstantAlpha( GrAlpha_t alpha )
{
#ifdef CRITICAL
    GlideMsg("grLfbConstantAlpha( %lu )\n", alpha );
#endif
}

DLLEXPORT void __stdcall
grLfbConstantDepth( FxU16 depth )
{
#ifdef CRITICAL
    GlideMsg("grLfbConstantDepth( %u )\n", depth );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
{
#ifdef CRITICAL
    GlideMsg("grLfbWriteColorSwizzle( %d, %d )\n",
        swizzleBytes, swapWords );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorFormat(GrColorFormat_t colorFormat)
{
#ifdef CRITICAL
    GlideMsg("grLfbWriteColorFormat( %u )\n", colorFormat );
#endif
}

<commit_msg>Added reminder comment<commit_after>//**************************************************************
//*            OpenGLide - Glide to OpenGL Wrapper
//*             http://openglide.sourceforge.net
//*
//*               Linear Frame Buffer Functions
//*
//*         OpenGLide is OpenSource under LGPL license
//*              Originaly made by Fabio Barros
//*      Modified by Paul for Glidos (http://www.glidos.net)
//**************************************************************

#include "GlOgl.h"
#include "Glextensions.h"
#include "GLRender.h"

#define BLUE_SCREEN (0x7ff)

inline void Convert565to8888( WORD *Buffer1, DWORD *Buffer2, DWORD Pixels )
{
    while ( Pixels )
    {
        *Buffer2++ = ( (*Buffer1) ? 0xFF000000 : 0x00000000 ) |   // A
                     ( (*Buffer1)     & 0x001F) << 19 |           // B
                     ( (*Buffer1)     & 0x07E0) << 5  |           // G
                     ( (*Buffer1++)   & 0xF800) >> 8;             // R
        Pixels--;
    }
}

inline void Convert565to5551( WORD *Buffer1, WORD *Buffer2, DWORD Pixels )
{
    while ( Pixels )
    {
        *Buffer2++ = ((*Buffer1) & 0xFFC0) |
                    (((*Buffer1) & 0x001F) << 1) |
                    ( (*Buffer1++) ? 0x0001 : 0x0000);
        Pixels--;
    }
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbLock( GrLock_t dwType,
           GrBuffer_t dwBuffer,
           GrLfbWriteMode_t dwWriteMode,
           GrOriginLocation_t dwOrigin,
           FxBool bPixelPipeline,
           GrLfbInfo_t *lfbInfo )
{
#ifdef CRITICAL
    GlideMsg("grLfbLock( %d, %d, %d, %d, %d, --- )\n", dwType, dwBuffer, dwWriteMode, dwOrigin, bPixelPipeline);
#endif

    int width = Glide.WindowWidth;
    int height = Glide.WindowHeight;

    RenderDrawTriangles( );

    if ( ( dwType & 1) == 0 )
    {
        FxU32 *buf = new FxU32[ width * height ];
        int i,
            j;

        glReadBuffer( dwBuffer == GR_BUFFER_BACKBUFFER
                      ? GL_BACK : GL_FRONT );

        glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void *)buf );

        for ( j = 0; j < height; j++ )
        {
            WORD    * line = Glide.SrcBuffer.Address + ( height - 1 - j ) * width;
            FxU32   * bufl = buf + j * width;

            for ( i = 0; i < width; i++ )
            {
                line[ i ] = (WORD)
                    ( ( ( bufl[i] & 0xf8 )     << 8 )
                    | ( ( bufl[i] & 0xfc00 )   >> 5 )
                    | ( ( bufl[i] & 0xf80000 ) >> 19 )
                    );
            }
        }

        delete[] buf;

        Glide.SrcBuffer.Lock = true;
        Glide.SrcBuffer.Type = dwType;
        Glide.SrcBuffer.Buffer = dwBuffer;
        Glide.SrcBuffer.WriteMode = dwWriteMode;

        lfbInfo->lfbPtr = Glide.SrcBuffer.Address;
    }
    else
    {
        for ( int i = 0; i < width * height; i++ )
        {
            Glide.DstBuffer.Address[ i ] = BLUE_SCREEN;
        }

        Glide.DstBuffer.Lock = true;
        Glide.DstBuffer.Type = dwType;
        Glide.DstBuffer.Buffer = dwBuffer;
        Glide.DstBuffer.WriteMode = dwWriteMode;

        lfbInfo->lfbPtr = Glide.DstBuffer.Address;
    }

    lfbInfo->strideInBytes = Glide.WindowWidth * 2;

    lfbInfo->writeMode = GR_LFBWRITEMODE_565;

    return FXTRUE;
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbUnlock( GrLock_t dwType, GrBuffer_t dwBuffer )
{
#ifdef CRITICAL
    GlideMsg("grLfbUnlock( %d, %d )\n", dwType, dwBuffer );
#endif

    int width = Glide.WindowWidth;
    int height = Glide.WindowHeight;

    if ( ( dwType & 1 ) == 0 )
    {
        if ( !Glide.SrcBuffer.Lock )
        {
            return FXFALSE;
        }

        Glide.SrcBuffer.Lock = false;

        return FXTRUE;
    }
    else
    {
        int x,
            y,
            maxx = 0,
            maxy = 0,
            minx = 2048,
            miny = 2048;

        if( !Glide.DstBuffer.Lock )
        {
            return FXFALSE;
        }

        for ( y = 0; y < height; y++ )
        {
            for ( x = 0; x < width; x++ )
            {
                if ( Glide.DstBuffer.Address[ y * width + x ] != BLUE_SCREEN )
                {
                    if ( x > maxx ) maxx = x;
                    if ( y > maxy ) maxy = y;
                    if ( x < minx ) minx = x;
                    if ( y < miny ) miny = y;
                }
            }
        }

        if ( maxx >= minx )
        {
            int xsize = maxx + 1 - minx;
            int ysize = maxy + 1 - miny;
            FxU32 *buf = new FxU32[ xsize * ysize ];

            glReadBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                          ? GL_BACK : GL_FRONT );

            glReadPixels( minx, height - miny-ysize,
                          xsize, ysize,
                          GL_RGBA, GL_UNSIGNED_BYTE, (void *) buf );

            for ( y = 0; y < ysize; y++ )
            {
                WORD    * line = Glide.DstBuffer.Address + ( miny + ysize - 1 - y ) *
                                 width + minx;
                FxU32   * bufl = buf + y * xsize;

                for ( x = 0; x < xsize; x++ )
                {
                    if ( line[ x ] != BLUE_SCREEN )
                    {
                        bufl[ x ] = ( ( (line[x] & 0x001f ) << 19)
                                  |   ( (line[x] & 0x07e0 ) << 5 )
                                  |   ( (line[x] & 0xf100 ) >> 8 )
                                  | 0xff000000);
                    }
                }
            }

            glDisable( GL_BLEND );

            glDisable( GL_TEXTURE_2D );

            glDrawBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                          ? GL_BACK : GL_FRONT );

            glRasterPos2i( minx,  miny + ysize );

            glDrawPixels( xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, (void *) buf );

            glDrawBuffer( OpenGL.RenderBuffer );

            /* PHBG: don't think this resetting of blend state is needed */
            if ( OpenGL.Blend )
            {
                glEnable( GL_BLEND );
            }

            if ( Glide.DstBuffer.Buffer != GR_BUFFER_BACKBUFFER )
            {
                glFlush( );
            }

            delete[] buf;
        }

        Glide.DstBuffer.Lock = false;

        return FXTRUE;
    }
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbReadRegion( GrBuffer_t src_buffer,
                 FxU32 src_x, FxU32 src_y,
                 FxU32 src_width, FxU32 src_height,
                 FxU32 dst_stride, void *dst_data )
{
#ifdef NOTDONE
    GlideMsg("grLfbReadRegion( %d, %d, %d, %d, %d, %d, --- )\n",
        src_buffer, src_x, src_y, src_width, src_height, dst_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD PixelsX, PixelsY;
    static DWORD Stride;

    RenderDrawTriangles( );

    switch ( src_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glReadBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glReadBuffer( GL_BACK );    break;
    }

    glReadPixels( src_x, src_y, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)Glide.SrcBuffer.Address );
//  glReadPixels( 320, 230, 300, 200, GL_RED, GL_UNSIGNED_BYTE, &Glide.SrcBuffer.Address );
//  glDrawPixels( 300, 200, GL_RED , GL_UNSIGNED_BYTE, Glide.SrcBuffer.Address );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbReadRegion" );
#endif

    return FXTRUE;
}

//----------------------------------------------------------------
DLLEXPORT FxBool __stdcall
grLfbWriteRegion( GrBuffer_t dst_buffer,
                  FxU32 dst_x, FxU32 dst_y,
                  GrLfbSrcFmt_t src_format,
                  FxU32 src_width, FxU32 src_height,
                  FxI32 src_stride, void *src_data )
{
#ifdef NOTDONE
    GlideMsg("grLfbWriteRegion( %d, %d, %d, %d, %d, %d, %d, --- )\n",
        dst_buffer, dst_x, dst_y, src_format, src_width, src_height, src_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD Pixels;

    RenderDrawTriangles( );

    if ( src_stride != (FxI32)src_width )
    {
//      Error( "grLfbWriteRegion: different width and stride.\n" );
        return FXTRUE;
    }

    switch ( dst_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glDrawBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glDrawBuffer( GL_BACK );    break;
    }

    glRasterPos2i( dst_x, dst_y );

    switch ( src_format )
    {
    case GR_LFB_SRC_FMT_565:
    case GR_LFB_SRC_FMT_555:
    case GR_LFB_SRC_FMT_1555:
    case GR_LFB_SRC_FMT_888:
        break;

    case GR_LFB_SRC_FMT_8888:
        break;

    case GR_LFB_SRC_FMT_565_DEPTH:
    case GR_LFB_SRC_FMT_555_DEPTH:
    case GR_LFB_SRC_FMT_1555_DEPTH:
    case GR_LFB_SRC_FMT_ZA16:
    case GR_LFB_SRC_FMT_RLE16:
        break;
    }

//  glDrawPixels( src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, Glide.SrcBuffer.Buffer );

    glDrawBuffer( OpenGL.RenderBuffer );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbWriteRegion" );
#endif

    return FXTRUE;
}

DLLEXPORT void __stdcall
grLfbConstantAlpha( GrAlpha_t alpha )
{
#ifdef CRITICAL
    GlideMsg("grLfbConstantAlpha( %lu )\n", alpha );
#endif
}

DLLEXPORT void __stdcall
grLfbConstantDepth( FxU16 depth )
{
#ifdef CRITICAL
    GlideMsg("grLfbConstantDepth( %u )\n", depth );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
{
#ifdef CRITICAL
    GlideMsg("grLfbWriteColorSwizzle( %d, %d )\n",
        swizzleBytes, swapWords );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorFormat(GrColorFormat_t colorFormat)
{
#ifdef CRITICAL
    GlideMsg("grLfbWriteColorFormat( %u )\n", colorFormat );
#endif
}

<|endoftext|>


<commit_before>//**************************************************************
//*            OpenGLide - Glide to OpenGL Wrapper
//*             http://openglide.sourceforge.net
//*
//*               Linear Frame Buffer Functions
//*
//*         OpenGLide is OpenSource under LGPL license
//*              Originaly made by Fabio Barros
//*      Modified by Paul for Glidos (http://www.glidos.net)
//**************************************************************

#include "GlOgl.h"
#include "Glextensions.h"
#include "GLRender.h"
#include "FormatConversion.h"

#define BLUE_SCREEN     (0x07FF)

// Will need to change this later
static FxU32 tempBuf[ 2048 * 2048 ];

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbLock( GrLock_t dwType,
           GrBuffer_t dwBuffer,
           GrLfbWriteMode_t dwWriteMode,
           GrOriginLocation_t dwOrigin,
           FxBool bPixelPipeline,
           GrLfbInfo_t *lfbInfo )
{
#ifdef OGL_CRITICAL
    GlideMsg( "grLfbLock( %d, %d, %d, %d, %d, --- )\n", dwType, dwBuffer, dwWriteMode, dwOrigin, bPixelPipeline );
#endif

    RenderDrawTriangles( );

    if ( dwType & 1 )
    {
        for ( int i = Glide.WindowTotalPixels - 1; i >= 0; --i )
        {
            Glide.DstBuffer.Address[ i ] = BLUE_SCREEN;
        }
        Glide.DstBuffer.Lock            = true;
        Glide.DstBuffer.Type            = dwType;
        Glide.DstBuffer.Buffer          = dwBuffer;
        Glide.DstBuffer.WriteMode       = dwWriteMode;
        Glide.DstBuffer.PixelPipeline   = bPixelPipeline;

        lfbInfo->lfbPtr = Glide.DstBuffer.Address;
    }
    else
    {
        int j;

        glReadBuffer( dwBuffer == GR_BUFFER_BACKBUFFER
                      ? GL_BACK : GL_FRONT );

        if ( dwOrigin == GR_ORIGIN_UPPER_LEFT )
        {
            if ( InternalConfig.OGLVersion > 1 )
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
                              (void *)Glide.DstBuffer.Address );
            }
            else
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT,
                              (void *)tempBuf );
                if ( InternalConfig.MMXEnable )
                {
                    MMXConvert5551to565( tempBuf, Glide.DstBuffer.Address, Glide.WindowTotalPixels );
                }
                else
                {
                    Convert5551to565( tempBuf, (DWORD*)Glide.DstBuffer.Address, Glide.WindowTotalPixels );
                }
            }

            for ( j = 0; j < Glide.WindowHeight; j++ )
            {
                memcpy( Glide.SrcBuffer.Address + ( j * Glide.WindowWidth ),
                        Glide.DstBuffer.Address + ( ( Glide.WindowHeight - 1 - j ) * Glide.WindowWidth ),
                        2 * Glide.WindowWidth );
            }
        }
        else
        {
            if ( InternalConfig.OGLVersion > 1 )
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
                              (void *)Glide.SrcBuffer.Address );
            }
            else
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT,
                              (void *)tempBuf );
                if ( InternalConfig.MMXEnable )
                {
                    MMXConvert5551to565( tempBuf, Glide.SrcBuffer.Address, Glide.WindowTotalPixels );
                }
                else
                {
                    Convert5551to565( tempBuf, (DWORD*)Glide.SrcBuffer.Address, Glide.WindowTotalPixels );
                }
            }
        }
        Glide.SrcBuffer.Lock            = true;
        Glide.SrcBuffer.Type            = dwType;
        Glide.SrcBuffer.Buffer          = dwBuffer;
        Glide.SrcBuffer.WriteMode       = dwWriteMode;
        Glide.SrcBuffer.PixelPipeline   = bPixelPipeline;

        lfbInfo->lfbPtr = Glide.SrcBuffer.Address;
    }

    lfbInfo->writeMode = GR_LFBWRITEMODE_565;
    lfbInfo->strideInBytes = Glide.WindowWidth * 2;

    return FXTRUE;
}

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbUnlock( GrLock_t dwType, GrBuffer_t dwBuffer )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbUnlock( %d, %d )\n", dwType, dwBuffer );
#endif

    if ( Glide.DstBuffer.Lock )
    {
        if ( dwType & 1 )
        {
            int ii,
                x,
                y,
                maxx = 0,
                maxy = 0,
                minx = 2048,
                miny = 2048;

            for ( ii = 0, x = 0, y = 0; ii < Glide.WindowTotalPixels; ii++ )
            {
                if ( Glide.DstBuffer.Address[ ii ] != BLUE_SCREEN )
                {
                    if ( x > maxx ) maxx = x;
                    if ( y > maxy ) maxy = y;
                    if ( x < minx ) minx = x;
                    if ( y < miny ) miny = y;
                }
                x++;
                if ( x == Glide.WindowWidth )
                {
                    x = 0;
                    y++;
                }
            }
            for ( y = 0; y < Glide.WindowHeight; y++ )
            {
                for ( x = 0; x < Glide.WindowWidth; x++ )
                {
                    if ( Glide.DstBuffer.Address[ y * Glide.WindowWidth + x ] != BLUE_SCREEN )
                    {
                        if ( x > maxx ) maxx = x;
                        if ( y > maxy ) maxy = y;
                        if ( x < minx ) minx = x;
                        if ( y < miny ) miny = y;
                    }
                }
            }

            if ( maxx >= minx )
            {
                int xsize = maxx + 1 - minx;
                int ysize = maxy + 1 - miny;

                glReadBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                            ? GL_BACK : GL_FRONT );

                if ( InternalConfig.OGLVersion > 1 )
                {
                    glReadPixels( minx, Glide.WindowHeight - miny - ysize,
                                  xsize, ysize,
                                  GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void *)tempBuf );
                }
                else
                {
                    glReadPixels( minx, Glide.WindowHeight - miny - ysize,
                                  xsize, ysize,
                                  GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT,
                                  (void *)tempBuf );
                    if ( InternalConfig.MMXEnable )
                    {
                        MMXConvert5551to565( tempBuf, tempBuf, xsize * ysize );
                    }
                    else
                    {
                        Convert5551to565( tempBuf, (DWORD*)tempBuf, xsize * ysize );
                    }
                }

                for ( y = 0; y < ysize; y++ )
                {
                    WORD    * line = Glide.DstBuffer.Address + ( miny + ysize - 1 - y ) *
                                        Glide.WindowWidth + minx;
                    WORD    * bufl = (WORD*)tempBuf + y * xsize;

                    for ( x = 0; x < xsize; x++ )
                    {
                        if ( line[ x ] != BLUE_SCREEN )
                        {
                            bufl[ x ] = line[ x ];
                        }
                    }
                }

                glDisable( GL_BLEND );

                glDisable( GL_TEXTURE_2D );

                glDrawBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                            ? GL_BACK : GL_FRONT );

                glRasterPos2i( minx,  miny + ysize );

                if ( ! Glide.DstBuffer.PixelPipeline )
                {
                    if ( InternalConfig.OGLVersion > 1 )
                    {
                        glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void *)tempBuf );
                    }
                    else
                    {
                        if ( InternalConfig.MMXEnable )
                        {
                            MMXConvert565to5551( tempBuf, tempBuf, xsize * ysize );
                        }
                        else
                        {
                            Convert565to5551( tempBuf, tempBuf, xsize * ysize );
                        }
                        glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT, (void *)tempBuf );
                    }
                }
                else
                {
      		        glEnable( GL_SCISSOR_TEST );
                    if ( InternalConfig.OGLVersion > 1 )
                    {
                        glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void *)tempBuf );
                    }
                    else
                    {
                        if ( InternalConfig.MMXEnable )
                        {
                            MMXConvert565to5551( tempBuf, tempBuf, xsize * ysize );
                        }
                        else
                        {
                            Convert565to5551( tempBuf, tempBuf, xsize * ysize );
                        }
                        glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT, (void *)tempBuf );
                    }
                    glDisable( GL_SCISSOR_TEST );
                }
                glDrawBuffer( OpenGL.RenderBuffer );

                /* PHBG: don't think this resetting of blend state is needed */
                if ( OpenGL.Blend )
                {
                    glEnable( GL_BLEND );
                }

                if ( Glide.DstBuffer.Buffer != GR_BUFFER_BACKBUFFER )
                {
                    glFlush( );
                }
            }

            Glide.DstBuffer.Lock = false;

            return FXTRUE;
        }
        else
        {
            Glide.SrcBuffer.Lock = false;

            return FXTRUE;
        }
    }
    else
    {
        return FXFALSE;
    }
}

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbReadRegion( GrBuffer_t src_buffer,
                 FxU32 src_x, FxU32 src_y,
                 FxU32 src_width, FxU32 src_height,
                 FxU32 dst_stride, void *dst_data )
{
#ifdef OGL_NOTDONE
    GlideMsg("grLfbReadRegion( %d, %d, %d, %d, %d, %d, --- )\n",
        src_buffer, src_x, src_y, src_width, src_height, dst_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD PixelsX, PixelsY;
    static DWORD Stride;

    RenderDrawTriangles( );

    switch ( src_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glReadBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glReadBuffer( GL_BACK );    break;
    }

    glReadPixels( src_x, src_y, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)Glide.SrcBuffer.Address );
//  glReadPixels( 320, 230, 300, 200, GL_RED, GL_UNSIGNED_BYTE, &Glide.SrcBuffer.Address );
//  glDrawPixels( 300, 200, GL_RED , GL_UNSIGNED_BYTE, Glide.SrcBuffer.Address );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbReadRegion" );
#endif

    return FXTRUE;
}

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbWriteRegion( GrBuffer_t dst_buffer,
                  FxU32 dst_x, FxU32 dst_y,
                  GrLfbSrcFmt_t src_format,
                  FxU32 src_width, FxU32 src_height,
                  FxI32 src_stride, void *src_data )
{
#ifdef OGL_NOTDONE
    GlideMsg("grLfbWriteRegion( %d, %d, %d, %d, %d, %d, %d, --- )\n",
        dst_buffer, dst_x, dst_y, src_format, src_width, src_height, src_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD Pixels;

    RenderDrawTriangles( );

    if ( src_stride != (FxI32)src_width )
    {
//      Error( "grLfbWriteRegion: different width and stride.\n" );
        return FXTRUE;
    }

    switch ( dst_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glDrawBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glDrawBuffer( GL_BACK );    break;
    }

    glRasterPos2i( dst_x, dst_y );

    switch ( src_format )
    {
    case GR_LFB_SRC_FMT_565:
    case GR_LFB_SRC_FMT_555:
    case GR_LFB_SRC_FMT_1555:
    case GR_LFB_SRC_FMT_888:
        break;

    case GR_LFB_SRC_FMT_8888:
        break;

    case GR_LFB_SRC_FMT_565_DEPTH:
    case GR_LFB_SRC_FMT_555_DEPTH:
    case GR_LFB_SRC_FMT_1555_DEPTH:
    case GR_LFB_SRC_FMT_ZA16:
    case GR_LFB_SRC_FMT_RLE16:
        break;
    }

//  glDrawPixels( src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, Glide.SrcBuffer.Buffer );

    glDrawBuffer( OpenGL.RenderBuffer );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbWriteRegion" );
#endif

    return FXTRUE;
}

DLLEXPORT void __stdcall
grLfbConstantAlpha( GrAlpha_t alpha )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbConstantAlpha( %lu )\n", alpha );
#endif
}

DLLEXPORT void __stdcall
grLfbConstantDepth( FxU16 depth )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbConstantDepth( %u )\n", depth );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorSwizzle( FxBool swizzleBytes, FxBool swapWords )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbWriteColorSwizzle( %d, %d )\n",
        swizzleBytes, swapWords );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorFormat( GrColorFormat_t colorFormat )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbWriteColorFormat( %u )\n", colorFormat );
#endif
}

<commit_msg>Fix a bug in the LockBuffer<commit_after>//**************************************************************
//*            OpenGLide - Glide to OpenGL Wrapper
//*             http://openglide.sourceforge.net
//*
//*               Linear Frame Buffer Functions
//*
//*         OpenGLide is OpenSource under LGPL license
//*              Originaly made by Fabio Barros
//*      Modified by Paul for Glidos (http://www.glidos.net)
//**************************************************************

#include "GlOgl.h"
#include "Glextensions.h"
#include "GLRender.h"
#include "FormatConversion.h"

#define BLUE_SCREEN     (0x07FF)

// Will need to change this later
static FxU32 tempBuf[ 2048 * 2048 ];

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbLock( GrLock_t dwType,
           GrBuffer_t dwBuffer,
           GrLfbWriteMode_t dwWriteMode,
           GrOriginLocation_t dwOrigin,
           FxBool bPixelPipeline,
           GrLfbInfo_t *lfbInfo )
{
#ifdef OGL_CRITICAL
    GlideMsg( "grLfbLock( %d, %d, %d, %d, %d, --- )\n", dwType, dwBuffer, dwWriteMode, dwOrigin, bPixelPipeline );
#endif

    RenderDrawTriangles( );

    if ( dwType & 1 )
    {
        for ( int i = Glide.WindowTotalPixels - 1; i >= 0; --i )
        {
            Glide.DstBuffer.Address[ i ] = BLUE_SCREEN;
        }
        Glide.DstBuffer.Lock            = true;
        Glide.DstBuffer.Type            = dwType;
        Glide.DstBuffer.Buffer          = dwBuffer;
        Glide.DstBuffer.WriteMode       = dwWriteMode;
        Glide.DstBuffer.PixelPipeline   = bPixelPipeline;

        lfbInfo->lfbPtr = Glide.DstBuffer.Address;
    }
    else
    {
        int j;

        glReadBuffer( dwBuffer == GR_BUFFER_BACKBUFFER
                      ? GL_BACK : GL_FRONT );

        if ( dwOrigin == GR_ORIGIN_UPPER_LEFT )
        {
            if ( InternalConfig.OGLVersion > 1 )
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
                              (void *)Glide.DstBuffer.Address );
            }
            else
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT,
                              (void *)tempBuf );
                if ( InternalConfig.MMXEnable )
                {
                    MMXConvert5551to565( tempBuf, Glide.DstBuffer.Address, Glide.WindowTotalPixels );
                }
                else
                {
                    Convert5551to565( tempBuf, (DWORD*)Glide.DstBuffer.Address, Glide.WindowTotalPixels );
                }
            }

            for ( j = 0; j < Glide.WindowHeight; j++ )
            {
                memcpy( Glide.SrcBuffer.Address + ( j * Glide.WindowWidth ),
                        Glide.DstBuffer.Address + ( ( Glide.WindowHeight - 1 - j ) * Glide.WindowWidth ),
                        2 * Glide.WindowWidth );
            }
        }
        else
        {
            if ( InternalConfig.OGLVersion > 1 )
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
                              (void *)Glide.SrcBuffer.Address );
            }
            else
            {
                glReadPixels( 0, 0,
                              Glide.WindowWidth, Glide.WindowHeight,
                              GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT,
                              (void *)tempBuf );
                if ( InternalConfig.MMXEnable )
                {
                    MMXConvert5551to565( tempBuf, Glide.SrcBuffer.Address, Glide.WindowTotalPixels );
                }
                else
                {
                    Convert5551to565( tempBuf, (DWORD*)Glide.SrcBuffer.Address, Glide.WindowTotalPixels );
                }
            }
        }
        Glide.SrcBuffer.Lock            = true;
        Glide.SrcBuffer.Type            = dwType;
        Glide.SrcBuffer.Buffer          = dwBuffer;
        Glide.SrcBuffer.WriteMode       = dwWriteMode;
        Glide.SrcBuffer.PixelPipeline   = bPixelPipeline;

        lfbInfo->lfbPtr = Glide.SrcBuffer.Address;
    }

    lfbInfo->writeMode = GR_LFBWRITEMODE_565;
    lfbInfo->strideInBytes = Glide.WindowWidth * 2;

    return FXTRUE;
}

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbUnlock( GrLock_t dwType, GrBuffer_t dwBuffer )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbUnlock( %d, %d )\n", dwType, dwBuffer );
#endif

    if ( dwType & 1 )
    {
        if ( ! Glide.DstBuffer.Lock )
        {
            return FXFALSE;
        }

        int ii,
            x,
            y,
            maxx = 0,
            maxy = 0,
            minx = 2048,
            miny = 2048;

        for ( ii = 0, x = 0, y = 0; ii < Glide.WindowTotalPixels; ii++ )
        {
            if ( Glide.DstBuffer.Address[ ii ] != BLUE_SCREEN )
            {
                if ( x > maxx ) maxx = x;
                if ( y > maxy ) maxy = y;
                if ( x < minx ) minx = x;
                if ( y < miny ) miny = y;
            }
            x++;
            if ( x == Glide.WindowWidth )
            {
                x = 0;
                y++;
            }
        }
        for ( y = 0; y < Glide.WindowHeight; y++ )
        {
            for ( x = 0; x < Glide.WindowWidth; x++ )
            {
                if ( Glide.DstBuffer.Address[ y * Glide.WindowWidth + x ] != BLUE_SCREEN )
                {
                    if ( x > maxx ) maxx = x;
                    if ( y > maxy ) maxy = y;
                    if ( x < minx ) minx = x;
                    if ( y < miny ) miny = y;
                }
            }
        }

        if ( maxx >= minx )
        {
            int xsize = maxx + 1 - minx;
            int ysize = maxy + 1 - miny;

            glReadBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                        ? GL_BACK : GL_FRONT );

            if ( InternalConfig.OGLVersion > 1 )
            {
                glReadPixels( minx, Glide.WindowHeight - miny - ysize,
                                xsize, ysize,
                                GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void *)tempBuf );
            }
            else
            {
                glReadPixels( minx, Glide.WindowHeight - miny - ysize,
                                xsize, ysize,
                                GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT,
                                (void *)tempBuf );
                if ( InternalConfig.MMXEnable )
                {
                    MMXConvert5551to565( tempBuf, tempBuf, xsize * ysize );
                }
                else
                {
                    Convert5551to565( tempBuf, (DWORD*)tempBuf, xsize * ysize );
                }
            }

            for ( y = 0; y < ysize; y++ )
            {
                WORD    * line = Glide.DstBuffer.Address + ( miny + ysize - 1 - y ) *
                                    Glide.WindowWidth + minx;
                WORD    * bufl = (WORD*)tempBuf + y * xsize;

                for ( x = 0; x < xsize; x++ )
                {
                    if ( line[ x ] != BLUE_SCREEN )
                    {
                        bufl[ x ] = line[ x ];
                    }
                }
            }

            glDisable( GL_BLEND );

            glDisable( GL_TEXTURE_2D );

            glDrawBuffer( Glide.DstBuffer.Buffer == GR_BUFFER_BACKBUFFER
                        ? GL_BACK : GL_FRONT );

            glRasterPos2i( minx,  miny + ysize );

            if ( ! Glide.DstBuffer.PixelPipeline )
            {
                if ( InternalConfig.OGLVersion > 1 )
                {
                    glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void *)tempBuf );
                }
                else
                {
                    if ( InternalConfig.MMXEnable )
                    {
                        MMXConvert565to5551( tempBuf, tempBuf, xsize * ysize );
                    }
                    else
                    {
                        Convert565to5551( tempBuf, tempBuf, xsize * ysize );
                    }
                    glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT, (void *)tempBuf );
                }
            }
            else
            {
      		    glEnable( GL_SCISSOR_TEST );
                if ( InternalConfig.OGLVersion > 1 )
                {
                    glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void *)tempBuf );
                }
                else
                {
                    if ( InternalConfig.MMXEnable )
                    {
                        MMXConvert565to5551( tempBuf, tempBuf, xsize * ysize );
                    }
                    else
                    {
                        Convert565to5551( tempBuf, tempBuf, xsize * ysize );
                    }
                    glDrawPixels( xsize, ysize, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1_EXT, (void *)tempBuf );
                }
                glDisable( GL_SCISSOR_TEST );
            }
            glDrawBuffer( OpenGL.RenderBuffer );

            /* PHBG: don't think this resetting of blend state is needed */
            if ( OpenGL.Blend )
            {
                glEnable( GL_BLEND );
            }

            if ( Glide.DstBuffer.Buffer != GR_BUFFER_BACKBUFFER )
            {
                glFlush( );
            }
        }

        Glide.DstBuffer.Lock = false;

        return FXTRUE;
    }
    else
    {
        if ( Glide.SrcBuffer.Lock )
        {
            Glide.SrcBuffer.Lock = false;

            return FXTRUE;
        }
        else
        {
            return FXFALSE;
        }
    }
}

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbReadRegion( GrBuffer_t src_buffer,
                 FxU32 src_x, FxU32 src_y,
                 FxU32 src_width, FxU32 src_height,
                 FxU32 dst_stride, void *dst_data )
{
#ifdef OGL_NOTDONE
    GlideMsg("grLfbReadRegion( %d, %d, %d, %d, %d, %d, --- )\n",
        src_buffer, src_x, src_y, src_width, src_height, dst_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD PixelsX, PixelsY;
    static DWORD Stride;

    RenderDrawTriangles( );

    switch ( src_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glReadBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glReadBuffer( GL_BACK );    break;
    }

    glReadPixels( src_x, src_y, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)Glide.SrcBuffer.Address );
//  glReadPixels( 320, 230, 300, 200, GL_RED, GL_UNSIGNED_BYTE, &Glide.SrcBuffer.Address );
//  glDrawPixels( 300, 200, GL_RED , GL_UNSIGNED_BYTE, Glide.SrcBuffer.Address );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbReadRegion" );
#endif

    return FXTRUE;
}

//*************************************************
DLLEXPORT FxBool __stdcall
grLfbWriteRegion( GrBuffer_t dst_buffer,
                  FxU32 dst_x, FxU32 dst_y,
                  GrLfbSrcFmt_t src_format,
                  FxU32 src_width, FxU32 src_height,
                  FxI32 src_stride, void *src_data )
{
#ifdef OGL_NOTDONE
    GlideMsg("grLfbWriteRegion( %d, %d, %d, %d, %d, %d, %d, --- )\n",
        dst_buffer, dst_x, dst_y, src_format, src_width, src_height, src_stride );
#endif

    static WORD *Buffer1;
    static DWORD *Buffer2;
    static DWORD Pixels;

    RenderDrawTriangles( );

    if ( src_stride != (FxI32)src_width )
    {
//      Error( "grLfbWriteRegion: different width and stride.\n" );
        return FXTRUE;
    }

    switch ( dst_buffer )
    {
    case GR_BUFFER_FRONTBUFFER:     glDrawBuffer( GL_FRONT );   break;
    case GR_BUFFER_BACKBUFFER:
    case GR_BUFFER_AUXBUFFER:       glDrawBuffer( GL_BACK );    break;
    }

    glRasterPos2i( dst_x, dst_y );

    switch ( src_format )
    {
    case GR_LFB_SRC_FMT_565:
    case GR_LFB_SRC_FMT_555:
    case GR_LFB_SRC_FMT_1555:
    case GR_LFB_SRC_FMT_888:
        break;

    case GR_LFB_SRC_FMT_8888:
        break;

    case GR_LFB_SRC_FMT_565_DEPTH:
    case GR_LFB_SRC_FMT_555_DEPTH:
    case GR_LFB_SRC_FMT_1555_DEPTH:
    case GR_LFB_SRC_FMT_ZA16:
    case GR_LFB_SRC_FMT_RLE16:
        break;
    }

//  glDrawPixels( src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, Glide.SrcBuffer.Buffer );

    glDrawBuffer( OpenGL.RenderBuffer );

#ifdef OPENGL_DEBUG
    GLErro( "grLfbWriteRegion" );
#endif

    return FXTRUE;
}

DLLEXPORT void __stdcall
grLfbConstantAlpha( GrAlpha_t alpha )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbConstantAlpha( %lu )\n", alpha );
#endif
}

DLLEXPORT void __stdcall
grLfbConstantDepth( FxU16 depth )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbConstantDepth( %u )\n", depth );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorSwizzle( FxBool swizzleBytes, FxBool swapWords )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbWriteColorSwizzle( %d, %d )\n",
        swizzleBytes, swapWords );
#endif
}

DLLEXPORT void __stdcall
grLfbWriteColorFormat( GrColorFormat_t colorFormat )
{
#ifdef OGL_CRITICAL
    GlideMsg("grLfbWriteColorFormat( %u )\n", colorFormat );
#endif
}

<|endoftext|>


<commit_before>#include "winrt_platform.h"
#include "xbl_manager.h"
#ifdef WINDOWS_STORE

#include "winrt_system.h"
using namespace Halley;

#include "winrt/Windows.ApplicationModel.h"
#include "winrt/Windows.ApplicationModel.Core.h"
#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Foundation.Diagnostics.h"
#include "winrt/Windows.Storage.h"
#include "winrt/Windows.Storage.FileProperties.h"
#include "winrt/Windows.Storage.Search.h"
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/Windows.System.Diagnostics.h"
#include "winrt/Windows.UI.Core.h"
#include "winrt/Windows.UI.ViewManagement.h"

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::ApplicationModel;
using namespace winrt::Windows::ApplicationModel::Core;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::ViewManagement;

#pragma comment(lib, "windowsapp")

class StdioDataReader : public ResourceDataReader {
public:

	StdioDataReader(const String& path)
	{
		_wfopen_s(&fp, path.getUTF16().c_str(), L"rb");
		if (!fp) {
			throw Exception("Unable to load " + path, HalleyExceptions::File);
		}
	}

	~StdioDataReader()
	{
		StdioDataReader::close();
	}

	size_t size() const override
	{
		const long startPos = ftell(fp);
		fseek(fp, 0, SEEK_END);
		const size_t size = size_t(ftell(fp));
		fseek(fp, startPos, SEEK_SET);
		return size;
	}

	int read(gsl::span<gsl::byte> dst) override
	{
		return int(fread(dst.data(), 1, dst.size_bytes(), fp));
	}

	void seek(int64_t pos, int whence) override
	{
		fseek(fp, long(pos), whence);
	}

	size_t tell() const override
	{
		return size_t(ftell(fp));
	}

	void close() override
	{
		if (fp) {
			fclose(fp);
			fp = nullptr;
		}
	}

private:
	FILE* fp = nullptr;
};

class WinRTWindow : public Window
{
public:
	WinRTWindow(CoreWindow window, const WindowDefinition& definition, WinRTSystem* system)
		: window(window)
		, system(system)
		, definition(definition.withSize(Vector2i(Vector2f(window.Bounds().Width, window.Bounds().Height))))
	{
		window.SizeChanged([=] (CoreWindow win, WindowSizeChangedEventArgs args)
		{
			notifySizeChange(Vector2i(Vector2f(args.Size().Width, args.Size().Height)));
		});

		window.KeyDown([=] (CoreWindow win, KeyEventArgs args)
		{
			args.Handled(true);
		});

		window.KeyUp([=] (CoreWindow win, KeyEventArgs args)
		{
			args.Handled(true);
		});

		window.Activated([=](CoreWindow win, WindowActivatedEventArgs args)
		{
			if (args.WindowActivationState() == CoreWindowActivationState::CodeActivated) {
				system->getPlatform()->recreateCloudSaveContainer();
			}
		});
	}

	void update(const WindowDefinition& def) override
	{
		auto curView = ApplicationView::GetForCurrentView();
		bool currentlyFullscreen = curView.IsFullScreenMode();
		bool wantsFullscreen = def.getWindowType() == WindowType::Fullscreen;
		if (currentlyFullscreen != wantsFullscreen) {
			if (wantsFullscreen) {
				curView.TryEnterFullScreenMode();
			} else {
				curView.ExitFullScreenMode();
			}
		}
	}

	void show() override
	{
	}

	void hide() override
	{
	}

	void setVsync(bool vsync) override
	{
	}

	void swap() override
	{
	}

	Rect4i getWindowRect() const override
	{
		auto bounds = window.Bounds();
		return Rect4i(Rect4f(bounds.X, bounds.Y, bounds.Width, bounds.Height));
		//return Rect4i(Vector2i(), Vector2i(1920, 1080));
	}

	const WindowDefinition& getDefinition() const override
	{
		return definition;
	}

	void* getNativeHandle() override
	{
		return winrt::get_abi(window);
	}

	String getNativeHandleType() override
	{
		return "CoreWindow";
	}

	void notifySizeChange(Vector2i size)
	{
		definition = definition.withSize(size);
		//definition = definition.withSize(Vector2i(1920, 1080));
	}

private:
	CoreWindow window;
	WindowDefinition definition;
	WinRTSystem* system;
};

void WinRTSystem::init()
{
	// Setup logging
	/*
	using namespace winrt::Windows::Foundation::Diagnostics;
	LoggingChannel channel(L"halleyLog", LoggingChannelOptions());
	FileLoggingSession session(L"halleyLog");
	session.AddLoggingChannel(channel);

	channel.LogMessage(L"Hello world!");
	session.CloseAndSaveToFileAsync();
	*/

	Logger::addSink(*this);
}

void WinRTSystem::deInit()
{
	Logger::removeSink(*this);
}

void WinRTSystem::log(LoggerLevel level, const String& msg)
{
#ifdef _DEBUG
	OutputDebugStringW((msg + "\n").getUTF16().c_str());
#endif
}

Path WinRTSystem::getAssetsPath(const Path& gamePath) const
{
	static auto path = String(winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path().data()) + String("/Assets/");
	return path;
}

Path WinRTSystem::getUnpackedAssetsPath(const Path& gamePath) const
{
	static auto path = String(winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path().data()) + String("/Assets/");
	return path;
}

std::unique_ptr<ResourceDataReader> WinRTSystem::getDataReader(String path, int64_t start, int64_t end)
{
	return std::make_unique<StdioDataReader>(path);
}

std::unique_ptr<GLContext> WinRTSystem::createGLContext()
{
	// Not supported
	return {};
}

std::shared_ptr<Window> WinRTSystem::createWindow(const WindowDefinition& window)
{
	return std::make_shared<WinRTWindow>(CoreWindow::GetForCurrentThread(), window, this);
}

void WinRTSystem::destroyWindow(std::shared_ptr<Window> window)
{
}

Vector2i WinRTSystem::getScreenSize(int n) const
{
	return Vector2i(1920, 1080);
}

Rect4i WinRTSystem::getDisplayRect(int screen) const
{
	return Rect4i(0, 0, 1920, 1080);
}

void WinRTSystem::showCursor(bool show)
{
	// TODO
}

std::shared_ptr<ISaveData> WinRTSystem::getStorageContainer(SaveDataType type, const String& containerName)
{
	String prefix = toString(type);
	if (!containerName.isEmpty()) {
		prefix = prefix + "/" + containerName;
	}
	return std::make_shared<WinRTLocalSave>(prefix);
}

bool WinRTSystem::generateEvents(VideoAPI* video, InputAPI* input)
{
	CoreWindow window = CoreWindow::GetForCurrentThread();
	CoreDispatcher dispatcher = window.Dispatcher();
	dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

	return true;
}

void WinRTSystem::setPlatform(WinRTPlatform* winrtPlatform)
{
	platform = winrtPlatform;
}

WinRTPlatform* WinRTSystem::getPlatform()
{
	return platform;
}

struct View : winrt::implements<View, IFrameworkView>
{
	View(WinRTSystem& system, std::function<void()>&& runnable)
		: system(system)
		, runnable(std::move(runnable))
	{}

	~View()
	{
		OutputDebugString(L"Bye");
	}

	void Initialize(CoreApplicationView const &view)
	{
		OutputDebugString(L"Initialized");
	}

	void Load(winrt::hstring entryPoint)
	{
	}

	void Uninitialize()
	{
		OutputDebugString(L"Uninitialized");
	}

	void Run()
	{
		CoreWindow window = CoreWindow::GetForCurrentThread();
		window.Activate();
		CoreDispatcher dispatcher = window.Dispatcher();
		dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

		runnable();
	}

	void SetWindow(CoreWindow const & window)
	{

	}

private:
	WinRTSystem& system;
	std::function<void()> runnable;
};

struct Source : winrt::implements<Source, IFrameworkViewSource>
{
	Source(WinRTSystem& system, std::function<void()>&& runnable)
		: system(system)
		, runnable(std::move(runnable))
	{}

	IFrameworkView CreateView()
	{
		return winrt::make<View>(system, std::move(runnable));
	}

private:
	WinRTSystem& system;
	std::function<void()> runnable;
};

void WinRTSystem::runGame(std::function<void()> runnable)
{
	winrt::init_apartment();
	ApplicationViewScaling::TrySetDisableLayoutScaling(true);
	CoreApplication::Run(winrt::make<Source>(*this, std::move(runnable)));
}

WinRTLocalSave::WinRTLocalSave(String prefix)
	: folder(makeFolder(prefix))
{
}

bool WinRTLocalSave::isReady() const
{
	return true;
}

Bytes WinRTLocalSave::getData(const String& path)
{
	return Concurrent::execute([&] () -> Bytes {
		try {
			auto file = folder.GetFileAsync(path.getUTF16().c_str()).get();
			auto buffer = FileIO::ReadBufferAsync(file).get();

			auto size = buffer.Length();
			Bytes result(size);
			auto dataReader = Streams::DataReader::FromBuffer(buffer);
			dataReader.ReadBytes(winrt::array_view<uint8_t>(result));

			return result;
		} catch (...) {
			return {};
		}
	}).get();
}

std::vector<String> WinRTLocalSave::enumerate(const String& root)
{
	return Concurrent::execute([&] () -> std::vector<String> {
		std::vector<String> result;
		try {
			auto files = folder.GetFilesAsync(winrt::Windows::Storage::Search::CommonFileQuery::OrderByName, 0, 256).get();
			for (auto& f: files) {
				String name = String(f.Name().c_str());
				if (name.startsWith(root)) {
					result.push_back(name);
				}
			}
		} catch (...) {}
		return result;
	}).get();
}

void WinRTLocalSave::setData(const String& path, const Bytes& data, bool commit)
{
	Concurrent::execute([&] () {
		auto file = folder.CreateFileAsync(path.getUTF16().c_str(), CreationCollisionOption::ReplaceExisting).get();
		FileIO::WriteBytesAsync(file, data).get();
	}).get(); // This .get() is not necessary, but gives me peace of mind
}

void WinRTLocalSave::removeData(const String& path)
{
	Concurrent::execute([&]() {
		try {
			auto file = folder.GetFileAsync(path.getUTF16().c_str()).get();
			file.DeleteAsync().get();
		}
		catch (...) {}
	}).get();
}

void WinRTLocalSave::commit()
{
}

StorageFolder WinRTLocalSave::makeFolder(String prefix)
{
	return Concurrent::execute([&] () -> StorageFolder {
		auto localFolder = ApplicationData::Current().LocalFolder();
		return localFolder.CreateFolderAsync(prefix.getUTF16().c_str(), CreationCollisionOption::OpenIfExists).get();
	}).get();
}

#endif
<commit_msg>UWP showCursor function working<commit_after>#include "winrt_platform.h"
#include "xbl_manager.h"
#ifdef WINDOWS_STORE

#include "winrt_system.h"
using namespace Halley;

#include "winrt/Windows.ApplicationModel.h"
#include "winrt/Windows.ApplicationModel.Core.h"
#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Foundation.Diagnostics.h"
#include "winrt/Windows.Storage.h"
#include "winrt/Windows.Storage.FileProperties.h"
#include "winrt/Windows.Storage.Search.h"
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/Windows.System.Diagnostics.h"
#include "winrt/Windows.UI.Core.h"
#include "winrt/Windows.UI.ViewManagement.h"

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::ApplicationModel;
using namespace winrt::Windows::ApplicationModel::Core;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::ViewManagement;

#pragma comment(lib, "windowsapp")

class StdioDataReader : public ResourceDataReader {
public:

	StdioDataReader(const String& path)
	{
		_wfopen_s(&fp, path.getUTF16().c_str(), L"rb");
		if (!fp) {
			throw Exception("Unable to load " + path, HalleyExceptions::File);
		}
	}

	~StdioDataReader()
	{
		StdioDataReader::close();
	}

	size_t size() const override
	{
		const long startPos = ftell(fp);
		fseek(fp, 0, SEEK_END);
		const size_t size = size_t(ftell(fp));
		fseek(fp, startPos, SEEK_SET);
		return size;
	}

	int read(gsl::span<gsl::byte> dst) override
	{
		return int(fread(dst.data(), 1, dst.size_bytes(), fp));
	}

	void seek(int64_t pos, int whence) override
	{
		fseek(fp, long(pos), whence);
	}

	size_t tell() const override
	{
		return size_t(ftell(fp));
	}

	void close() override
	{
		if (fp) {
			fclose(fp);
			fp = nullptr;
		}
	}

private:
	FILE* fp = nullptr;
};

class WinRTWindow : public Window
{
public:
	WinRTWindow(CoreWindow window, const WindowDefinition& definition, WinRTSystem* system)
		: window(window)
		, system(system)
		, definition(definition.withSize(Vector2i(Vector2f(window.Bounds().Width, window.Bounds().Height))))
	{
		window.SizeChanged([=] (CoreWindow win, WindowSizeChangedEventArgs args)
		{
			notifySizeChange(Vector2i(Vector2f(args.Size().Width, args.Size().Height)));
		});

		window.KeyDown([=] (CoreWindow win, KeyEventArgs args)
		{
			args.Handled(true);
		});

		window.KeyUp([=] (CoreWindow win, KeyEventArgs args)
		{
			args.Handled(true);
		});

		window.Activated([=](CoreWindow win, WindowActivatedEventArgs args)
		{
			if (args.WindowActivationState() == CoreWindowActivationState::CodeActivated) {
				system->getPlatform()->recreateCloudSaveContainer();
			}
		});
	}

	void update(const WindowDefinition& def) override
	{
		auto curView = ApplicationView::GetForCurrentView();
		bool currentlyFullscreen = curView.IsFullScreenMode();
		bool wantsFullscreen = def.getWindowType() == WindowType::Fullscreen;
		if (currentlyFullscreen != wantsFullscreen) {
			if (wantsFullscreen) {
				curView.TryEnterFullScreenMode();
			} else {
				curView.ExitFullScreenMode();
			}
		}
	}

	void show() override
	{
	}

	void hide() override
	{
	}

	void setVsync(bool vsync) override
	{
	}

	void swap() override
	{
	}

	Rect4i getWindowRect() const override
	{
		auto bounds = window.Bounds();
		return Rect4i(Rect4f(bounds.X, bounds.Y, bounds.Width, bounds.Height));
		//return Rect4i(Vector2i(), Vector2i(1920, 1080));
	}

	const WindowDefinition& getDefinition() const override
	{
		return definition;
	}

	void* getNativeHandle() override
	{
		return winrt::get_abi(window);
	}

	String getNativeHandleType() override
	{
		return "CoreWindow";
	}

	void notifySizeChange(Vector2i size)
	{
		definition = definition.withSize(size);
		//definition = definition.withSize(Vector2i(1920, 1080));
	}

private:
	CoreWindow window;
	WindowDefinition definition;
	WinRTSystem* system;
};

void WinRTSystem::init()
{
	// Setup logging
	/*
	using namespace winrt::Windows::Foundation::Diagnostics;
	LoggingChannel channel(L"halleyLog", LoggingChannelOptions());
	FileLoggingSession session(L"halleyLog");
	session.AddLoggingChannel(channel);

	channel.LogMessage(L"Hello world!");
	session.CloseAndSaveToFileAsync();
	*/

	Logger::addSink(*this);
}

void WinRTSystem::deInit()
{
	Logger::removeSink(*this);
}

void WinRTSystem::log(LoggerLevel level, const String& msg)
{
#ifdef _DEBUG
	OutputDebugStringW((msg + "\n").getUTF16().c_str());
#endif
}

Path WinRTSystem::getAssetsPath(const Path& gamePath) const
{
	static auto path = String(winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path().data()) + String("/Assets/");
	return path;
}

Path WinRTSystem::getUnpackedAssetsPath(const Path& gamePath) const
{
	static auto path = String(winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path().data()) + String("/Assets/");
	return path;
}

std::unique_ptr<ResourceDataReader> WinRTSystem::getDataReader(String path, int64_t start, int64_t end)
{
	return std::make_unique<StdioDataReader>(path);
}

std::unique_ptr<GLContext> WinRTSystem::createGLContext()
{
	// Not supported
	return {};
}

std::shared_ptr<Window> WinRTSystem::createWindow(const WindowDefinition& window)
{
	return std::make_shared<WinRTWindow>(CoreWindow::GetForCurrentThread(), window, this);
}

void WinRTSystem::destroyWindow(std::shared_ptr<Window> window)
{
}

Vector2i WinRTSystem::getScreenSize(int n) const
{
	return Vector2i(1920, 1080);
}

Rect4i WinRTSystem::getDisplayRect(int screen) const
{
	return Rect4i(0, 0, 1920, 1080);
}

void WinRTSystem::showCursor(bool show)
{
	CoreWindow window = CoreWindow::GetForCurrentThread();
	if (show) {
		window.PointerCursor ( CoreCursor( CoreCursorType::Arrow, 0 ) );
	}
	else {
		window.PointerCursor( nullptr );
	}
}

std::shared_ptr<ISaveData> WinRTSystem::getStorageContainer(SaveDataType type, const String& containerName)
{
	String prefix = toString(type);
	if (!containerName.isEmpty()) {
		prefix = prefix + "/" + containerName;
	}
	return std::make_shared<WinRTLocalSave>(prefix);
}

bool WinRTSystem::generateEvents(VideoAPI* video, InputAPI* input)
{
	CoreWindow window = CoreWindow::GetForCurrentThread();
	CoreDispatcher dispatcher = window.Dispatcher();
	dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

	return true;
}

void WinRTSystem::setPlatform(WinRTPlatform* winrtPlatform)
{
	platform = winrtPlatform;
}

WinRTPlatform* WinRTSystem::getPlatform()
{
	return platform;
}

struct View : winrt::implements<View, IFrameworkView>
{
	View(WinRTSystem& system, std::function<void()>&& runnable)
		: system(system)
		, runnable(std::move(runnable))
	{}

	~View()
	{
		OutputDebugString(L"Bye");
	}

	void Initialize(CoreApplicationView const &view)
	{
		OutputDebugString(L"Initialized");
	}

	void Load(winrt::hstring entryPoint)
	{
	}

	void Uninitialize()
	{
		OutputDebugString(L"Uninitialized");
	}

	void Run()
	{
		CoreWindow window = CoreWindow::GetForCurrentThread();
		window.Activate();
		CoreDispatcher dispatcher = window.Dispatcher();
		dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

		runnable();
	}

	void SetWindow(CoreWindow const & window)
	{

	}

private:
	WinRTSystem& system;
	std::function<void()> runnable;
};

struct Source : winrt::implements<Source, IFrameworkViewSource>
{
	Source(WinRTSystem& system, std::function<void()>&& runnable)
		: system(system)
		, runnable(std::move(runnable))
	{}

	IFrameworkView CreateView()
	{
		return winrt::make<View>(system, std::move(runnable));
	}

private:
	WinRTSystem& system;
	std::function<void()> runnable;
};

void WinRTSystem::runGame(std::function<void()> runnable)
{
	winrt::init_apartment();
	ApplicationViewScaling::TrySetDisableLayoutScaling(true);
	CoreApplication::Run(winrt::make<Source>(*this, std::move(runnable)));
}

WinRTLocalSave::WinRTLocalSave(String prefix)
	: folder(makeFolder(prefix))
{
}

bool WinRTLocalSave::isReady() const
{
	return true;
}

Bytes WinRTLocalSave::getData(const String& path)
{
	return Concurrent::execute([&] () -> Bytes {
		try {
			auto file = folder.GetFileAsync(path.getUTF16().c_str()).get();
			auto buffer = FileIO::ReadBufferAsync(file).get();

			auto size = buffer.Length();
			Bytes result(size);
			auto dataReader = Streams::DataReader::FromBuffer(buffer);
			dataReader.ReadBytes(winrt::array_view<uint8_t>(result));

			return result;
		} catch (...) {
			return {};
		}
	}).get();
}

std::vector<String> WinRTLocalSave::enumerate(const String& root)
{
	return Concurrent::execute([&] () -> std::vector<String> {
		std::vector<String> result;
		try {
			auto files = folder.GetFilesAsync(winrt::Windows::Storage::Search::CommonFileQuery::OrderByName, 0, 256).get();
			for (auto& f: files) {
				String name = String(f.Name().c_str());
				if (name.startsWith(root)) {
					result.push_back(name);
				}
			}
		} catch (...) {}
		return result;
	}).get();
}

void WinRTLocalSave::setData(const String& path, const Bytes& data, bool commit)
{
	Concurrent::execute([&] () {
		auto file = folder.CreateFileAsync(path.getUTF16().c_str(), CreationCollisionOption::ReplaceExisting).get();
		FileIO::WriteBytesAsync(file, data).get();
	}).get(); // This .get() is not necessary, but gives me peace of mind
}

void WinRTLocalSave::removeData(const String& path)
{
	Concurrent::execute([&]() {
		try {
			auto file = folder.GetFileAsync(path.getUTF16().c_str()).get();
			file.DeleteAsync().get();
		}
		catch (...) {}
	}).get();
}

void WinRTLocalSave::commit()
{
}

StorageFolder WinRTLocalSave::makeFolder(String prefix)
{
	return Concurrent::execute([&] () -> StorageFolder {
		auto localFolder = ApplicationData::Current().LocalFolder();
		return localFolder.CreateFolderAsync(prefix.getUTF16().c_str(), CreationCollisionOption::OpenIfExists).get();
	}).get();
}

#endif
<|endoftext|>