<commit_before>#include "filters.hh"

namespace Kakoune
{

void colorize_regex(DisplayBuffer& display_buffer,
                    const boost::regex& ex, Color color)
{
    for (auto atom_it = display_buffer.begin();
         atom_it != display_buffer.end(); ++atom_it)
    {
        boost::match_results<BufferIterator> matches;
        if (boost::regex_search(atom_it->begin(), atom_it->end(),
                                matches, ex, boost::match_nosubs))
        {
            const BufferIterator& begin = matches.begin()->first;
            if (begin != atom_it->begin())
                atom_it = ++display_buffer.split(atom_it, begin);

            const BufferIterator& end = matches.begin()->second;
            if (end != atom_it->end())
                atom_it = display_buffer.split(atom_it, end);

            atom_it->fg_color() = color;
        }
    }
}

void colorize_cplusplus(DisplayBuffer& display_buffer)
{
    static boost::regex preprocessor("(\\`|(?<=\\n))\\h*#\\h*[^\\n]*(?=\\n)");
    colorize_regex(display_buffer, preprocessor, Color::Magenta);

    static boost::regex comments("//[^\\n]*\\n");
    colorize_regex(display_buffer, comments, Color::Cyan);

    static boost::regex strings("(?<!')\"(\\\\\"|[^\"])*\"");
    colorize_regex(display_buffer, strings, Color::Magenta);

    static boost::regex values("\\<(true|false|NULL|nullptr)\\>|-?\\d+[fdiu]?|'\\\\?[^']?'");
    colorize_regex(display_buffer, values, Color::Red);

    static boost::regex builtin_types("\\<(void|int|float|bool|size_t)\\>");
    colorize_regex(display_buffer, builtin_types, Color::Yellow);

    static boost::regex control_keywords("\\<(while|for|if|else|do|switch|case|default|goto|break|continue|return|using|try|catch|throw)\\>");
    colorize_regex(display_buffer, control_keywords, Color::Blue);

    //static boost::regex operators("->|\\+|\\-|\\*|/|\\\\|\\&|\\|\\^|[<>=!+-]=|=|\\(|\\)|\\[|\\]|\\{|\\}|\\<(not|and|or|xor)\\>");
    //colorize_regex(display_buffer, operators, Color::Green);

    static boost::regex types_keywords("\\<(const|auto|namespace|static|volatile|class|struct|enum|union|public|protected|private|template)\\>");
    colorize_regex(display_buffer, types_keywords, Color::Green);
}

void expand_tabulations(DisplayBuffer& display_buffer)
{
    const int tabstop = 8;
    for (auto atom_it = display_buffer.begin();
         atom_it != display_buffer.end(); ++atom_it)
    {
        for (BufferIterator it = atom_it->begin(); it != atom_it->end(); ++it)
        {
            if (*it == '\t')
            {
                if (it != atom_it->begin())
                    atom_it = ++display_buffer.split(atom_it, it);

                if (it+1 != atom_it->end())
                    atom_it = display_buffer.split(atom_it, it+1);

                BufferCoord pos = it.buffer().line_and_column_at(it);

                int column = 0;
                for (auto line_it = it.buffer().iterator_at({pos.line, 0});
                     line_it != it; ++line_it)
                {
                    assert(*line_it != '\n');
                    if (*line_it == '\t')
                        column += tabstop - (column % tabstop);
                    else
                       ++column;
                }

                int count = tabstop - (column % tabstop);
                display_buffer.replace_atom_content(atom_it,
                                                    std::string(count, ' '));
            }
        }
    }
}

void show_line_numbers(DisplayBuffer& display_buffer)
{
    const Buffer& buffer = display_buffer.front().begin().buffer();
    BufferCoord coord = buffer.line_and_column_at(display_buffer.begin()->begin());

    int last_line = buffer.line_and_column_at(display_buffer.back().end()-1).line;

    for (; coord.line <= last_line; ++coord.line)
    {
        BufferIterator line_start = buffer.iterator_at(coord);
        DisplayBuffer::iterator atom_it = display_buffer.atom_containing(line_start);
        if (atom_it != display_buffer.end())
        {
            if (atom_it->begin() != line_start)
            {
                if (not atom_it->splitable())
                    continue;

                atom_it = ++display_buffer.split(atom_it, line_start);
            }
            atom_it = display_buffer.insert(
                atom_it,
                DisplayAtom(atom_it->coord(),
                            atom_it->begin(), atom_it->begin(),
                            Color::Black, Color::White));

            char buffer[6];
            snprintf(buffer, 6, "%3d ", coord.line);
            display_buffer.replace_atom_content(atom_it, buffer);
        }
    }
}

}
<commit_msg>Filters: rewrote colorize_regex<commit_after>#include "filters.hh"

namespace Kakoune
{

void colorize_regex(DisplayBuffer& display_buffer,
                    const boost::regex& ex, Color color)
{
    BufferIterator display_begin = display_buffer.begin()->begin();
    BufferIterator display_end   = display_buffer.back().end();

    boost::regex_iterator<BufferIterator> re_it(display_begin, display_end,
                                                ex, boost::match_nosubs);
    boost::regex_iterator<BufferIterator> re_end;
    DisplayBuffer::iterator atom_it = display_buffer.begin();
    for (; re_it != re_end; ++re_it)
    {
        BufferIterator begin = (*re_it)[0].first;
        BufferIterator end   = (*re_it)[0].second;
        auto begin_atom_it = display_buffer.atom_containing(begin, atom_it);
        auto end_atom_it   = display_buffer.atom_containing(end, atom_it);
        if (begin_atom_it == end_atom_it)
        {
            if (begin_atom_it->begin() != begin)
                begin_atom_it = ++display_buffer.split(begin_atom_it, begin);
            if (begin_atom_it->end() != end)
                begin_atom_it = display_buffer.split(begin_atom_it, end);

            begin_atom_it->fg_color() = color;
        }
        atom_it = begin_atom_it;
    }
}

void colorize_cplusplus(DisplayBuffer& display_buffer)
{
    static boost::regex preprocessor("(\\`|(?<=\\n))\\h*#\\h*[^\\n]*(?=\\n)");
    colorize_regex(display_buffer, preprocessor, Color::Magenta);

    static boost::regex comments("//[^\\n]*\\n");
    colorize_regex(display_buffer, comments, Color::Cyan);

    static boost::regex strings("(?<!')\"(\\\\\"|[^\"])*\"");
    colorize_regex(display_buffer, strings, Color::Magenta);

    static boost::regex values("\\<(true|false|NULL|nullptr)\\>|-?\\d+[fdiu]?|'\\\\?[^']?'");
    colorize_regex(display_buffer, values, Color::Red);

    static boost::regex builtin_types("\\<(void|int|float|bool|size_t)\\>");
    colorize_regex(display_buffer, builtin_types, Color::Yellow);

    static boost::regex control_keywords("\\<(while|for|if|else|do|switch|case|default|goto|break|continue|return|using|try|catch|throw)\\>");
    colorize_regex(display_buffer, control_keywords, Color::Blue);

    //static boost::regex operators("->|\\+|\\-|\\*|/|\\\\|\\&|\\|\\^|[<>=!+-]=|=|\\(|\\)|\\[|\\]|\\{|\\}|\\<(not|and|or|xor)\\>");
    //colorize_regex(display_buffer, operators, Color::Green);

    static boost::regex types_keywords("\\<(const|auto|namespace|static|volatile|class|struct|enum|union|public|protected|private|template)\\>");
    colorize_regex(display_buffer, types_keywords, Color::Green);
}

void expand_tabulations(DisplayBuffer& display_buffer)
{
    const int tabstop = 8;
    for (auto atom_it = display_buffer.begin();
         atom_it != display_buffer.end(); ++atom_it)
    {
        for (BufferIterator it = atom_it->begin(); it != atom_it->end(); ++it)
        {
            if (*it == '\t')
            {
                if (it != atom_it->begin())
                    atom_it = ++display_buffer.split(atom_it, it);

                if (it+1 != atom_it->end())
                    atom_it = display_buffer.split(atom_it, it+1);

                BufferCoord pos = it.buffer().line_and_column_at(it);

                int column = 0;
                for (auto line_it = it.buffer().iterator_at({pos.line, 0});
                     line_it != it; ++line_it)
                {
                    assert(*line_it != '\n');
                    if (*line_it == '\t')
                        column += tabstop - (column % tabstop);
                    else
                       ++column;
                }

                int count = tabstop - (column % tabstop);
                display_buffer.replace_atom_content(atom_it,
                                                    std::string(count, ' '));
            }
        }
    }
}

void show_line_numbers(DisplayBuffer& display_buffer)
{
    const Buffer& buffer = display_buffer.front().begin().buffer();
    BufferCoord coord = buffer.line_and_column_at(display_buffer.begin()->begin());

    int last_line = buffer.line_and_column_at(display_buffer.back().end()-1).line;

    for (; coord.line <= last_line; ++coord.line)
    {
        BufferIterator line_start = buffer.iterator_at(coord);
        DisplayBuffer::iterator atom_it = display_buffer.atom_containing(line_start);
        if (atom_it != display_buffer.end())
        {
            if (atom_it->begin() != line_start)
            {
                if (not atom_it->splitable())
                    continue;

                atom_it = ++display_buffer.split(atom_it, line_start);
            }
            atom_it = display_buffer.insert(
                atom_it,
                DisplayAtom(atom_it->coord(),
                            atom_it->begin(), atom_it->begin(),
                            Color::Black, Color::White));

            char buffer[6];
            snprintf(buffer, 6, "%3d ", coord.line);
            display_buffer.replace_atom_content(atom_it, buffer);
        }
    }
}

}
<|endoftext|>


<commit_before><commit_msg>requested changes to pdngen, fixing forloops and early return if insts is empty<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <string>
#include <boost/tokenizer.hpp>
#include <vector>
#include <list>

// puts the argv input from the program into a list
std::list<std::string> GetInput(int argc, char **argcv);

// outputs parameters to the program for debugging
void Output(std::list<std::string> input);

// grabbed from UserHostInfo from rshell.cpp
// the gains from refactoring aren't worth bothering
std::string CurrentPwd();

bool UnknownArgs(const std::list<std::string> input);
std::list<std::string> Split(std::string args);
int main(int argc, char **argv) {
  auto input = GetInput(argc, argv);
  Output(input);

  //    DIR *test = opendir("test");
  //    readdir(test);
  //    struct stat *buf= new struct stat;
  //    stat("test",buf);
  //    buf->st_gid
}

std::list<std::string> GetInput(int argc, char **argv) {
  using namespace std;
  list<string> input;
  for (int i = 0; i < argc; i++) {
    string piece(argv[i]);
    input.push_back(piece);
  }
  return input;
}
void Output(std::list<std::string> input) {
  for (const auto &element : input)
    std::cout << element << std::endl;
}

std::string CurrentPwd() {
  char *rawpwd = get_current_dir_name();
  if (rawpwd == NULL) {
    perror("get_current_dir_name returned NULL");
    exit(1);
  }
  std::string pwd(rawpwd);
  delete rawpwd;
  return pwd;
}
std::list<std::string> Split(std::string args) {
  std::string foo = args;
  std::list<std::string> test;
  return test;
}
bool UnknownArgs(const std::list<std::string> input) {
  input.empty();
  return true;
}
<commit_msg>added UnknownArgs and Split<commit_after>#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <string>
#include <boost/tokenizer.hpp>
#include <vector>
#include <list>
#include <set>
#include <ctype.h>
// puts the argv input from the program into a list
std::list<std::string> GetInput(int argc, char **argcv);

// outputs parameters to the program for debugging
void Output(std::list<std::string> input);

// grabbed from UserHostInfo from rshell.cpp
// the gains from refactoring aren't worth bothering
std::string CurrentPwd();

// iterate each character of each element with a - to look for unknown args
bool UnknownArgs(std::list<std::string> input);
std::set<std::string> Split(std::list<std::string> input);
int main(int argc, char **argv) {
  auto input = GetInput(argc, argv);
  Output(input);
  if(UnknownArgs(input))
    std::cout << "oh no" << std::endl;

  //    DIR *test = opendir("test");
  //    readdir(test);
  //    struct stat *buf= new struct stat;
  //    stat("test",buf);
  //    buf->st_gid
}

std::list<std::string> GetInput(int argc, char **argv) {
  using namespace std;
  list<string> input;
  for (int i = 0; i < argc; i++) {
    string piece(argv[i]);
    input.push_back(piece);
  }
  return input;
}
void Output(std::list<std::string> input) {
  for (const auto &element : input)
    std::cout << element << std::endl;
}

std::string CurrentPwd() {
  char *rawpwd = get_current_dir_name();
  if (rawpwd == NULL) {
    perror("get_current_dir_name returned NULL");
    exit(1);
  }
  std::string pwd(rawpwd);
  delete rawpwd;
  return pwd;
}
std::set<std::string> Split(std::list<std::string> input) {
  std::set<std::string> args;
  input.pop_front();
  for (auto& item : input) {
    if (item[0] == '-') {
      item.erase(item.begin());
      for(const auto& letter : item) {
        args.emplace(letter);
        }
    }
  }
  return args;
}
bool UnknownArgs(std::list<std::string> input) {
  for (auto &item : input) {
    if (item[0] == '-') {
      item.erase(item.begin());
      for (const auto &letter : item) {
        if (letter != 'l' && letter != 'a' && tolower(letter) != 'r')
          return true;
      }
    }
  }
  return false;
}
<|endoftext|>


<commit_before>/* vim:set noet sts=0 sw=2 ts=2: */
#include <string>
#include <vector>

using namespace std;

#define FIRST_TOKEN 257
/* 256 possible for char, plus one */

#define check_next(pos, test_char)	input[ts->position + pos] == test_char

namespace fusion {

	struct token {
		enum token_t {
			/* keywords */
			TOK_ELSE = FIRST_TOKEN, TOK_IF, TOK_TRUE, TOK_FALSE, TOK_NIL, TOK_WHILE,
			TOK_IN, TOK_NEW, TOK_EXTENDS, TOK_FOR,
			/* binary operators with more than one char*/
			TOK_BOOLAND, TOK_BOOLOR, TOK_RSHIFT, TOK_LSHIFT, TOK_EQ, TOK_NEQ, TOK_GE,
			TOK_LE, TOK_CONCAT,
			/* extra tokens */
			TOK_VARARG, TOK_EOF, TOK_INT, TOK_NUM, TOK_STRING, TOK_NAME
		} type;
		string self;
	};

	struct TokenizerState {
		char current_char;
		int current_line;
		int position;
		vector<token> tokens;
		string input;
	};
}
<commit_msg>src/ftoken.hpp: refactor 'using namespace std'<commit_after>/* vim:set noet sts=0 sw=2 ts=2: */
#include <string>
#include <vector>

#define FIRST_TOKEN 257
/* 256 possible for char, plus one */
#define check_next(pos, test_char)	input[ts->position + pos] == test_char

namespace fusion {

	struct token {
		enum token_t {
			/* keywords */
			TOK_ELSE = FIRST_TOKEN, TOK_IF, TOK_TRUE, TOK_FALSE, TOK_NIL, TOK_WHILE,
			TOK_IN, TOK_NEW, TOK_EXTENDS, TOK_FOR,
			/* binary operators with more than one char*/
			TOK_BOOLAND, TOK_BOOLOR, TOK_RSHIFT, TOK_LSHIFT, TOK_EQ, TOK_NEQ, TOK_GE,
			TOK_LE, TOK_CONCAT,
			/* extra tokens */
			TOK_VARARG, TOK_EOF, TOK_INT, TOK_NUM, TOK_STRING, TOK_NAME
		} type;
		std::string self;
	};

	struct TokenizerState {
		char current_char;
		int current_line;
		int position;
		std::vector<token> tokens;
		std::string input;
	};
}
<|endoftext|>


<commit_before>#include "map.h"

#include "graphics.h"
#include "sprite.h"

namespace {
  const unsigned int rows = 30;
  const unsigned int cols = 40;
}

Map::Map(Graphics& graphics) {
  init_sprites(graphics);

  tiles = std::vector<std::vector<TileType>>(rows, std::vector<TileType>(cols, Map::WATER));

  // TODO randomly generate map instead maybe
  int cy = 5;
  for (int x = 0; x < cols; ++x) {
    for (int y = 0; y < cy; ++y) {
      tiles[y][x] = Map::LAND;
    }

    if (x % 2 == 0) {
      int d = rand() % 4;
      if (d == 1) cy--;
      if (d == 2) cy++;

      if (cy < 2) cy = 2;
      if (cy > 7) cy = 7;
    }
  }
}

void Map::draw(Graphics& graphics) {
  for (int y = 0; y < rows; ++y) {
    for (int x = 0; x < cols; ++x) {
      sprites[tiles[y][x]]->draw(graphics, 16 * x, 16 * y);
    }
  }
}

void Map::update(unsigned int elapsed) {
  // TODO figure out chance of spreading fire and oil and shit
}

bool Map::sailable(unsigned int x, unsigned int y) {
  if (x >= cols) return false;
  if (y >= rows) return false;
  return tiles[y][x] != Map::LAND;
}

void Map::init_sprites(Graphics& graphics) {
  sprites[Map::WATER] = boost::shared_ptr<Sprite>(new Sprite(graphics, "map", 0, 0, 16, 16));
  sprites[Map::OIL] = boost::shared_ptr<Sprite>(new Sprite(graphics, "map", 16, 0, 16, 16));
  sprites[Map::LAND] = boost::shared_ptr<Sprite>(new Sprite(graphics, "map", 32, 0, 16, 16));
}

void Map::spread_oil() {
  // TODO spread oil around to adjacent blocks
}

void Map::spread_fire() {
  // TODO spread fire to nearby oil
}
<commit_msg>Improve map generator<commit_after>#include "map.h"

#include "graphics.h"
#include "sprite.h"

namespace {
  const unsigned int rows = 30;
  const unsigned int cols = 40;
}

Map::Map(Graphics& graphics) {
  init_sprites(graphics);

  tiles = std::vector<std::vector<TileType>>(rows, std::vector<TileType>(cols, Map::WATER));

  // TODO randomly generate map instead maybe
  int cy = 5;
  for (int x = 0; x < cols; ++x) {
    for (int y = 0; y < cy; ++y) {
      tiles[y][x] = Map::LAND;
    }

    if (x % 2 == 1) {
      int d = rand() % 4;
      if (d == 0) cy--;
      if (d == 1) cy++;

      if (cy < 2) cy = 2;
      if (cy > 7) cy = 7;
    }
  }
}

void Map::draw(Graphics& graphics) {
  for (int y = 0; y < rows; ++y) {
    for (int x = 0; x < cols; ++x) {
      sprites[tiles[y][x]]->draw(graphics, 16 * x, 16 * y);
    }
  }
}

void Map::update(unsigned int elapsed) {
  // TODO figure out chance of spreading fire and oil and shit
}

bool Map::sailable(unsigned int x, unsigned int y) {
  if (x >= cols) return false;
  if (y >= rows) return false;
  return tiles[y][x] != Map::LAND;
}

void Map::init_sprites(Graphics& graphics) {
  sprites[Map::WATER] = boost::shared_ptr<Sprite>(new Sprite(graphics, "map", 0, 0, 16, 16));
  sprites[Map::OIL] = boost::shared_ptr<Sprite>(new Sprite(graphics, "map", 16, 0, 16, 16));
  sprites[Map::LAND] = boost::shared_ptr<Sprite>(new Sprite(graphics, "map", 32, 0, 16, 16));
}

void Map::spread_oil() {
  // TODO spread oil around to adjacent blocks
}

void Map::spread_fire() {
  // TODO spread fire to nearby oil
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <primitives/block.h>

#include <hash.h>
#include <streams.h>
#include <tinyformat.h>
#include <utilstrencodings.h>
#include <crypto/common.h>

uint256 CBlockHeader::GetHash() const
{
    std::vector<unsigned char> vch(80);
    CVectorWriter ss(SER_NETWORK, PROTOCOL_VERSION, vch, 0);
    ss << *this;
    return HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (const auto& tx : vtx) {
        s << "  " << tx->ToString() << "\n";
    }
    return s.str();
}
<commit_msg>Use correct Serialization Type in `CBlockHeader::GetHash()` (#4068)<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <primitives/block.h>

#include <hash.h>
#include <streams.h>
#include <tinyformat.h>
#include <utilstrencodings.h>
#include <crypto/common.h>

uint256 CBlockHeader::GetHash() const
{
    std::vector<unsigned char> vch(80);
    CVectorWriter ss(SER_GETHASH, PROTOCOL_VERSION, vch, 0);
    ss << *this;
    return HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (const auto& tx : vtx) {
        s << "  " << tx->ToString() << "\n";
    }
    return s.str();
}
<|endoftext|>


<commit_before>#include "LeverEntity.h"

LeverEntity::LeverEntity(){}
LeverEntity::~LeverEntity(){}

int LeverEntity::Initialize(int entityID, PhysicsComponent * pComp, GraphicsComponent * gComp, float interactionDistance)
{
	int result = 0;
	this->InitializeBase(entityID, pComp, gComp, nullptr);

	this->m_isActive = 0;
	this->m_needSync = false;
	this->m_range = interactionDistance;
	this->SyncComponents();
	return result;
}

int LeverEntity::Update(float dT, InputHandler * inputHandler)
{
	int result = 0;
	if (m_animationActive)
	{
		static float lastFrameRotValue = 0;
		PhysicsComponent* ptr = this->GetPhysicsComponent();
		DirectX::XMMATRIX rot;
		float frameRot = m_animSpeed * dT;
		if (m_targetRot == 0)
		{
			if (m_currRot  + frameRot < m_targetRot)
			{
				m_currRot += frameRot;
				rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(frameRot));

				lastFrameRotValue = m_currRot;
			}
			else {
				m_animationActive = false;
				m_currRot = m_targetRot;
				this->m_subject.Notify(this->m_entityID, EVENT(EVENT::LEVER_DEACTIVE + this->m_isActive));
				DirectX::XMFLOAT3 pos;
				DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
				SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LEVER, pos, false, false);
				rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(m_targetRot - lastFrameRotValue));

			}
		}
		else
		{
			 if (m_currRot - frameRot > m_targetRot)
			{
				m_currRot -= frameRot;
				rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(-frameRot));
				lastFrameRotValue = m_currRot;
			}
			 else {
				 m_animationActive = false;
				 m_currRot = m_targetRot;
				 this->m_subject.Notify(this->m_entityID, EVENT(EVENT::LEVER_DEACTIVE + this->m_isActive));
				 DirectX::XMFLOAT3 pos;
				 DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
				 SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LEVER, pos, false, false);
				 rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(m_targetRot + (lastFrameRotValue * -1)));

			 }
		}

		ptr->PC_OBB.ort = DirectX::XMMatrixMultiply(ptr->PC_OBB.ort, rot);
		this->SyncComponents();

	}
	return result;
}

int LeverEntity::React(int entityID, EVENT reactEvent)
{
	int result = 0;
	//If a lever receives a LEVER::ACTIVATED or BUTTON::ACTIVATE event, deactivate this lever
	if (reactEvent == EVENT::LEVER_ACTIVE || reactEvent == EVENT::BUTTON_ACTIVE)
	{
		this->m_isActive = false;
		if (m_currRot == m_activatedRotation) //check if the animation needs to be reset
		{
			m_animationActive = true;
			m_targetRot = 0;
		}
		this->SyncComponents();

	}
	return result;
}

int LeverEntity::CheckPressed(DirectX::XMFLOAT3 playerPos)
{
	if (m_animationActive)
		return 0;
	if (abs(DirectX::XMVectorGetX(this->m_pComp->PC_pos) - playerPos.x) < this->m_range
		&& abs(DirectX::XMVectorGetY(this->m_pComp->PC_pos) - playerPos.y) < this->m_range
		&& abs(DirectX::XMVectorGetZ(this->m_pComp->PC_pos) - playerPos.z) < this->m_range)
	{
		this->m_isActive = !this->m_isActive;

		if (m_isActive){
			m_targetRot = m_activatedRotation;
		}
		else{
			m_targetRot = 0;
		}
		m_animationActive = true;
		this->m_needSync = true;

	}
	return 0;
}

void LeverEntity::SetSyncState(LeverSyncState * newSyncState)
{
	if (newSyncState != nullptr)
	{
		//The player is always the cause of the state change
		this->m_isActive = newSyncState->isActive;
		this->m_animationActive = newSyncState->isAnimationActive;
		this->m_subject.Notify(this->m_entityID, EVENT(EVENT::LEVER_DEACTIVE + this->m_isActive));

		DirectX::XMFLOAT3 pos;
		DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
		SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LEVER, pos, false, false);

	}
}

LeverSyncState * LeverEntity::GetSyncState()
{
	LeverSyncState* result = nullptr;
	if (this->m_needSync)
	{
		result = new LeverSyncState{this->m_entityID, this->m_isActive};
		this->m_needSync = false;
	}
	return result;
}
<commit_msg>UPDATE<commit_after>#include "LeverEntity.h"

LeverEntity::LeverEntity(){}
LeverEntity::~LeverEntity(){}

int LeverEntity::Initialize(int entityID, PhysicsComponent * pComp, GraphicsComponent * gComp, float interactionDistance)
{
	int result = 0;
	this->InitializeBase(entityID, pComp, gComp, nullptr);

	this->m_isActive = 0;
	this->m_needSync = false;
	this->m_range = interactionDistance;
	this->SyncComponents();
	return result;
}

int LeverEntity::Update(float dT, InputHandler * inputHandler)
{
	int result = 0;
	if (m_animationActive)
	{
		static float lastFrameRotValue = 0;
		PhysicsComponent* ptr = this->GetPhysicsComponent();
		DirectX::XMMATRIX rot;
		float frameRot = m_animSpeed * dT;
		if (m_targetRot == 0)
		{
			if (m_currRot  + frameRot < m_targetRot)
			{
				m_currRot += frameRot;
				rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(frameRot));

				lastFrameRotValue = m_currRot;
			}
			else {
				m_animationActive = false;
				m_currRot = m_targetRot;
				this->m_subject.Notify(this->m_entityID, EVENT(EVENT::LEVER_DEACTIVE + this->m_isActive));
				DirectX::XMFLOAT3 pos;
				DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
				SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LEVER, pos, false, false);
				rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(m_targetRot - lastFrameRotValue));

			}
		}
		else
		{
			 if (m_currRot - frameRot > m_targetRot)
			{
				m_currRot -= frameRot;
				rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(-frameRot));
				lastFrameRotValue = m_currRot;
			}
			 else {
				 m_animationActive = false;
				 m_currRot = m_targetRot;
				 this->m_subject.Notify(this->m_entityID, EVENT(EVENT::LEVER_DEACTIVE + this->m_isActive));
				 DirectX::XMFLOAT3 pos;
				 DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
				 SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LEVER, pos, false, false);
				 rot = DirectX::XMMatrixRotationAxis(ptr->PC_OBB.ort.r[2], DirectX::XMConvertToRadians(m_targetRot + (lastFrameRotValue * -1)));

			 }
		}

		ptr->PC_OBB.ort = DirectX::XMMatrixMultiply(ptr->PC_OBB.ort, rot);
		this->SyncComponents();

	}
	return result;
}

int LeverEntity::React(int entityID, EVENT reactEvent)
{
	int result = 0;
	//If a lever receives a LEVER::ACTIVATED or BUTTON::ACTIVATE event, deactivate this lever
	if (reactEvent == EVENT::LEVER_ACTIVE || reactEvent == EVENT::BUTTON_ACTIVE)
	{
		this->m_isActive = false;
		if (m_currRot == m_activatedRotation) //check if the animation needs to be reset
		{
			m_animationActive = true;
			m_targetRot = 0;
		}
		this->SyncComponents();

	}
	return result;
}

int LeverEntity::CheckPressed(DirectX::XMFLOAT3 playerPos)
{
	if (m_animationActive)
		return 0;
	if (abs(DirectX::XMVectorGetX(this->m_pComp->PC_pos) - playerPos.x) < this->m_range
		&& abs(DirectX::XMVectorGetY(this->m_pComp->PC_pos) - playerPos.y) < this->m_range
		&& abs(DirectX::XMVectorGetZ(this->m_pComp->PC_pos) - playerPos.z) < this->m_range)
	{
		this->m_isActive = !this->m_isActive;

		if (m_isActive){
			m_targetRot = m_activatedRotation;
		}
		else{
			m_targetRot = 0;
		}
		m_animationActive = true;
		this->m_needSync = true;

	}
	return 0;
}

void LeverEntity::SetSyncState(LeverSyncState * newSyncState)
{
	if (newSyncState != nullptr)
	{
		//The player is always the cause of the state change
		this->m_isActive = newSyncState->isActive;
		this->m_animationActive = newSyncState->isAnimationActive;
		this->m_animationActive = !this->m_animationActive;
		this->m_subject.Notify(this->m_entityID, EVENT(EVENT::LEVER_DEACTIVE + this->m_isActive));

		DirectX::XMFLOAT3 pos;
		DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
		SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LEVER, pos, false, false);

	}
}

LeverSyncState * LeverEntity::GetSyncState()
{
	LeverSyncState* result = nullptr;
	if (this->m_needSync)
	{
		result = new LeverSyncState{this->m_entityID, this->m_isActive};
		this->m_needSync = false;
	}
	return result;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "Stroika/Frameworks/StroikaPreComp.h"

#include    <mutex>
#include    <iostream>

#include    "Stroika/Foundation/Execution/CommandLine.h"
#include    "Stroika/Foundation/Execution/Event.h"
#include    "Stroika/Foundation/Memory/Optional.h"
#include    "Stroika/Foundation/IO/Network/HTTP/Headers.h"
#include    "Stroika/Foundation/IO/Network/NetworkInterfaces.h"
#include    "Stroika/Foundation/IO/Network/Listener.h"

#include    "Stroika/Frameworks/WebServer/ConnectionManager.h"

using   namespace std;

using   namespace Stroika::Foundation;
using   namespace Stroika::Foundation::IO::Network;
using   namespace Stroika::Frameworks::WebServer;

using   Characters::String;
using   Containers::Sequence;
using   Memory::Optional;

int main (int argc, const char* argv[])
{
    try {
        ConnectionManager   cm; // use??? @todo??

        auto onConnect = [](Socket s) {
            Execution::Thread runConnectionOnAnotherThread ([s]() {
                // now read
                Connection conn (s);
                conn.ReadHeaders ();    // bad API. Must rethink...
                conn.GetResponse ().AddHeader (IO::Network::HTTP::HeaderName::kServer, L"stroika-web-server-demo");
                String url = conn.GetRequest ().fURL.GetFullURL ();
				DbgTrace (L"Serving page %s", url.c_str ());
                conn.GetResponse ().writeln (L"
Hi Mom
");
                conn.GetResponse ().SetContentType (DataExchange::PredefinedInternetMediaType::Text_HTML_CT ());
                conn.GetResponse ().End ();
            });
            runConnectionOnAnotherThread.SetThreadName (L"Connection Thread");  // SHOULD use a fancier name (connection#)
            runConnectionOnAnotherThread.Start ();
            runConnectionOnAnotherThread.WaitForDone ();    // maybe save these in connection mgr so we can force them all shut down...
        };
        Listener l (SocketAddress (Network::V4::kAddrAny, 8080), onConnect);
        Execution::Event ().Wait ();    // wait forever - til user hits ctrl-c
    }
    catch (...) {
        cerr << "Exception - terminating..." << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<commit_msg>Runastyle<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "Stroika/Frameworks/StroikaPreComp.h"

#include    <mutex>
#include    <iostream>

#include    "Stroika/Foundation/Execution/CommandLine.h"
#include    "Stroika/Foundation/Execution/Event.h"
#include    "Stroika/Foundation/Memory/Optional.h"
#include    "Stroika/Foundation/IO/Network/HTTP/Headers.h"
#include    "Stroika/Foundation/IO/Network/NetworkInterfaces.h"
#include    "Stroika/Foundation/IO/Network/Listener.h"

#include    "Stroika/Frameworks/WebServer/ConnectionManager.h"

using   namespace std;

using   namespace Stroika::Foundation;
using   namespace Stroika::Foundation::IO::Network;
using   namespace Stroika::Frameworks::WebServer;

using   Characters::String;
using   Containers::Sequence;
using   Memory::Optional;

int main (int argc, const char* argv[])
{
    try {
        ConnectionManager   cm; // use??? @todo??

        auto onConnect = [](Socket s) {
            Execution::Thread runConnectionOnAnotherThread ([s]() {
                // now read
                Connection conn (s);
                conn.ReadHeaders ();    // bad API. Must rethink...
                conn.GetResponse ().AddHeader (IO::Network::HTTP::HeaderName::kServer, L"stroika-web-server-demo");
                String url = conn.GetRequest ().fURL.GetFullURL ();
                DbgTrace (L"Serving page %s", url.c_str ());
                conn.GetResponse ().writeln (L"
Hi Mom
");
                conn.GetResponse ().SetContentType (DataExchange::PredefinedInternetMediaType::Text_HTML_CT ());
                conn.GetResponse ().End ();
            });
            runConnectionOnAnotherThread.SetThreadName (L"Connection Thread");  // SHOULD use a fancier name (connection#)
            runConnectionOnAnotherThread.Start ();
            runConnectionOnAnotherThread.WaitForDone ();    // maybe save these in connection mgr so we can force them all shut down...
        };
        Listener l (SocketAddress (Network::V4::kAddrAny, 8080), onConnect);
        Execution::Event ().Wait ();    // wait forever - til user hits ctrl-c
    }
    catch (...) {
        cerr << "Exception - terminating..." << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * A library for controlling a Microchip rn2xx3 LoRa radio.
 *
 * @Author JP Meijers
 * @Author Nicolas Schteinschraber
 * @Date 18/12/2015
 *
 */

#include "Arduino.h"
#include "rn2xx3.h"

extern "C" {
#include <string.h>
#include <stdlib.h>
}

/*
  @param serial Needs to be an already opened stream to write to and read from.
*/
#ifdef SoftwareSerial_h
rn2xx3::rn2xx3(SoftwareSerial& serial, Stream& debugSerial):
_serial(serial),_debugSerial(debugSerial)
{
  _serial.setTimeout(2000);
}
#endif

rn2xx3::rn2xx3(HardwareSerial& serial, Stream& debugSerial):
_serial(serial),_debugSerial(debugSerial)
{
  _serial.setTimeout(2000);
}

void rn2xx3::autobaud()
{
  String response = "";
  while (response=="")
  {
    delay(1000);
    _serial.write((byte)0x00);
    _serial.write(0x55);
    _serial.println();
    _serial.println("sys get ver");
    response = _serial.readStringUntil('\n');
  }
}

RN2xx3_t rn2xx3::configureModuleType()
{
  String version = sysver();
  String model = version.substring(2,6);
  switch (model.toInt()) {
    case 2903:
      _moduleType = RN2903;
      break;
    case 2483:
      _moduleType = RN2483;
      break;
    default:
      _moduleType = RN_NA;
      break;
  }
  return _moduleType;
}
String rn2xx3::hweui()
{
  delay(100);
  while(_serial.available())
  {
    _serial.read();
  }
  _serial.println("sys get hweui");
  String addr = _serial.readStringUntil('\n');
  addr.trim();
  return addr;
}

String rn2xx3::sysver()
{
  delay(100);
  while(_serial.available())
    _serial.read();
  _serial.println("sys get ver");
  String ver = _serial.readStringUntil('\n');
  ver.trim();
  return ver;
}

bool rn2xx3::init()
{
  if(_appeui=="0")
  {
    return false;
  }
  else if(_otaa==true)
  {
    return init(_appeui, _appskey);
  }
  else
  {
    return init(_devAddr, _appskey, _nwkskey);
  }
}

bool rn2xx3::initOTAA(String AppEUI, String AppKey)
{
  return init(AppEUI, AppKey);
}

bool rn2xx3::init(String AppEUI, String AppKey)
{
  _otaa = true;
  _appeui = AppEUI;
  _nwkskey = "0";
  _appskey = AppKey; //reuse the variable
  String receivedData;

  //clear serial buffer
  while(_serial.available())
    _serial.read();

  _serial.println("sys get hweui");
  String addr = _serial.readStringUntil('\n');
  addr.trim();

  switch (_moduleType) {
    case RN2903:
      _serial.println("mac reset");
      break;
    case RN2483:
      _serial.println("mac reset 868");
      break;
    default:
      // we shouldn't go forward with the init
      return false;
  }
  receivedData = _serial.readStringUntil('\n');

  _serial.println("mac set appeui "+_appeui);
  receivedData = _serial.readStringUntil('\n');

  _serial.println("mac set appkey "+_appskey);
  receivedData = _serial.readStringUntil('\n');

  if(addr!="" && addr.length() == 16)
  {
    _serial.println("mac set deveui "+addr);
  }
  else
  {
    _serial.println("mac set deveui "+_default_deveui);
  }
  receivedData = _serial.readStringUntil('\n');

  if (_moduleType == RN2903)
  {
    _serial.println("mac set pwridx 5");
  }
  else
  {
    _serial.println("mac set pwridx 1");
  }
  receivedData = _serial.readStringUntil('\n');

  _serial.println("mac set adr off");
  receivedData = _serial.readStringUntil('\n');

  if (_moduleType == RN2483)
  {
    _serial.println("mac set rx2 3 869525000");
    receivedData = _serial.readStringUntil('\n');
  }

  _serial.setTimeout(30000);
  _serial.println("mac save");
  receivedData = _serial.readStringUntil('\n');

  bool joined = false;

  for(int i=0; i<2 && !joined; i++)
  {
    _serial.println("mac join otaa");
    receivedData = _serial.readStringUntil('\n');
    receivedData = _serial.readStringUntil('\n');

    if(receivedData.startsWith("accepted"))
    {
      joined=true;
      delay(1000);
    }
    else
    {
      delay(1000);
    }
  }
  _serial.setTimeout(2000);
  return joined;
}

bool rn2xx3::initABP(String devAddr, String AppSKey, String NwkSKey)
{
  return init(devAddr, AppSKey, NwkSKey);
}

bool rn2xx3::init(String devAddr, String AppSKey, String NwkSKey)
{
  _otaa = false;
  _devAddr = devAddr;
  _appskey = AppSKey;
  _nwkskey = NwkSKey;
  String receivedData;

  //clear serial buffer
  while(_serial.available())
    _serial.read();

  switch (_moduleType) {
    case RN2903:
      _serial.println("mac reset");
      _serial.readStringUntil('\n');
      break;
    case RN2483:
      _serial.println("mac reset 868");
      _serial.readStringUntil('\n');
      _serial.println("mac set rx2 3 869525000");
      _serial.readStringUntil('\n');
      break;
    default:
      // we shouldn't go forward with the init
      return false;
  }

  _serial.println("mac set nwkskey "+_nwkskey);
  _serial.readStringUntil('\n');
  _serial.println("mac set appskey "+_appskey);
  _serial.readStringUntil('\n');

  _serial.println("mac set devaddr "+_devAddr);
  _serial.readStringUntil('\n');

  _serial.println("mac set adr off");
  _serial.readStringUntil('\n');
  _serial.println("mac set ar off");
  _serial.readStringUntil('\n');

  if (_moduleType == RN2903)
  {
    _serial.println("mac set pwridx 5");
  }
  else
  {
    _serial.println("mac set pwridx 1");
  }
  _serial.readStringUntil('\n');
  _serial.println("mac set dr 5"); //0= min, 7=max
  _serial.readStringUntil('\n');

  _serial.setTimeout(60000);
  _serial.println("mac save");
  _serial.readStringUntil('\n');
  _serial.println("mac join abp");
  receivedData = _serial.readStringUntil('\n');
  receivedData = _serial.readStringUntil('\n');

  _serial.setTimeout(2000);
  delay(1000);

  if(receivedData.startsWith("accepted"))
  {
    return true;
    //with abp we can always join successfully as long as the keys are valid
  }
  else
  {
    return false;
  }
}

void rn2xx3::tx(String data)
{
  txUncnf(data); //we are unsure which mode we're in. Better not to wait for acks.
}

void rn2xx3::txCnf(String data)
{
  txData("mac tx cnf 1 ", data, true);
}

void rn2xx3::txUncnf(String data)
{
  txData("mac tx uncnf 1 ", data, true);
}

void rn2xx3::txData(String data, bool shouldEncode)
{
  txData("mac tx uncnf 1 ", data, shouldEncode);
}

bool rn2xx3::txData(String command, String data, bool shouldEncode)
{
  bool send_success = false;
  uint8_t busy_count = 0;
  uint8_t retry_count = 0;

  //clear serial buffer
  while(_serial.available())
    _serial.read();

  while(!send_success)
  {
    //retransmit a maximum of 10 times
    retry_count++;
    if(retry_count>10)
    {
      return false;
    }

    _serial.print(command);
    if(shouldEncode)
    {
      sendEncoded(data);
    }
    else
    {
      _serial.print(data);
    }
    _serial.println();
    String receivedData = _serial.readStringUntil('\n');

    if(receivedData.startsWith("ok"))
    {
      _serial.setTimeout(30000);
      receivedData = _serial.readStringUntil('\n');
      _serial.setTimeout(2000);

      if(receivedData.startsWith("mac_tx_ok"))
      {
        //SUCCESS!!
        send_success = true;
        return true;
      }

      else if(receivedData.startsWith("mac_rx"))
      {
        //we received data downstream
        //TODO: handle received data -
        // this can be done by returning a struct containing:
        // 1. a boolean for confirmed message acks'
        // 2. a boolean for received data
        // 3. a string/char array for the downlink data
        send_success = true;
        return true;
      }

      else if(receivedData.startsWith("mac_err"))
      {
        init();
      }

      else if(receivedData.startsWith("invalid_data_len"))
      {
        //this should never happen if the prototype worked
        send_success = true;
        return false;
      }

      else if(receivedData.startsWith("radio_tx_ok"))
      {
        //SUCCESS!!
        send_success = true;
        return true;
      }

      else if(receivedData.startsWith("radio_err"))
      {
        //This should never happen. If it does, something major is wrong.
        init();
      }

      else
      {
        //unknown response
        //init();
      }
    }

    else if(receivedData.startsWith("invalid_param"))
    {
      //should not happen if we typed the commands correctly
      send_success = true;
      return false;
    }

    else if(receivedData.startsWith("not_joined"))
    {
      init();
    }

    else if(receivedData.startsWith("no_free_ch"))
    {
      //retry
      delay(1000);
    }

    else if(receivedData.startsWith("silent"))
    {
      init();
    }

    else if(receivedData.startsWith("frame_counter_err_rejoin_needed"))
    {
      init();
    }

    else if(receivedData.startsWith("busy"))
    {
      busy_count++;

      if(busy_count>=10)
      {
        init();
      }
      else
      {
        delay(1000);
      }
    }

    else if(receivedData.startsWith("mac_paused"))
    {
      init();
    }

    else if(receivedData.startsWith("invalid_data_len"))
    {
      //should not happen if the prototype worked
      send_success = true;
      return false;
    }

    else
    {
      //unknown response after mac tx command
      init();
    }
  }

  return false; //should never reach this
}

void rn2xx3::sendEncoded(String input)
{
  char working;
  char buffer[3];
  for (unsigned i=0; i<input.length(); i++)
  {
    working = input.charAt(i);
    sprintf(buffer, "%02x", int(working));
    _serial.print(buffer);
  }
}

String rn2xx3::base16encode(String input)
{
  char charsOut[input.length()*2+1];
  char charsIn[input.length()+1];
  input.trim();
  input.toCharArray(charsIn, input.length()+1);

  unsigned i = 0;
  for(i = 0; i<input.length()+1; i++)
  {
    if(charsIn[i] == '\0') break;

    int value = int(charsIn[i]);

    char buffer[3];
    sprintf(buffer, "%02x", value);
    charsOut[2*i] = buffer[0];
    charsOut[2*i+1] = buffer[1];
  }
  charsOut[2*i] = '\0';
  String toReturn = String(charsOut);
  return toReturn;
}

String rn2xx3::base16decode(String input)
{
  char charsIn[input.length()+1];
  char charsOut[input.length()/2+1];
  input.trim();
  input.toCharArray(charsIn, input.length()+1);

  unsigned i = 0;
  for(i = 0; i<input.length()/2+1; i++)
  {
    if(charsIn[i*2] == '\0') break;
    if(charsIn[i*2+1] == '\0') break;

    char toDo[2];
    toDo[0] = charsIn[i*2];
    toDo[1] = charsIn[i*2+1];
    int out = strtoul(toDo, 0, 16);

    if(out<128)
    {
      charsOut[i] = char(out);
    }
  }
  charsOut[i] = '\0';
  return charsOut;
}

void rn2xx3::setDR(int dr)
{
  if(dr>=0 && dr<=5)
  {
    delay(100);
    while(_serial.available())
      _serial.read();
    _serial.print("mac set dr ");
    _serial.println(dr);
    _serial.readStringUntil('\n');
  }
}

void rn2xx3::sleep(long msec)
{
  _serial.print("sys sleep ");
  _serial.println(msec);
}

String rn2xx3::sendRawCommand(String command)
{
  delay(100);
  while(_serial.available())
    _serial.read();
  _serial.println(command);
  String ret = _serial.readStringUntil('\n');
  ret.trim();
  return ret;
}
<commit_msg>Call configureModuleType internally.<commit_after>/*
 * A library for controlling a Microchip rn2xx3 LoRa radio.
 *
 * @Author JP Meijers
 * @Author Nicolas Schteinschraber
 * @Date 18/12/2015
 *
 */

#include "Arduino.h"
#include "rn2xx3.h"

extern "C" {
#include <string.h>
#include <stdlib.h>
}

/*
  @param serial Needs to be an already opened stream to write to and read from.
*/
#ifdef SoftwareSerial_h
rn2xx3::rn2xx3(SoftwareSerial& serial, Stream& debugSerial):
_serial(serial),_debugSerial(debugSerial)
{
  _serial.setTimeout(2000);
}
#endif

rn2xx3::rn2xx3(HardwareSerial& serial, Stream& debugSerial):
_serial(serial),_debugSerial(debugSerial)
{
  _serial.setTimeout(2000);
}

void rn2xx3::autobaud()
{
  String response = "";
  while (response=="")
  {
    delay(1000);
    _serial.write((byte)0x00);
    _serial.write(0x55);
    _serial.println();
    _serial.println("sys get ver");
    response = _serial.readStringUntil('\n');
  }
}

RN2xx3_t rn2xx3::configureModuleType()
{
  String version = sysver();
  String model = version.substring(2,6);
  switch (model.toInt()) {
    case 2903:
      _moduleType = RN2903;
      break;
    case 2483:
      _moduleType = RN2483;
      break;
    default:
      _moduleType = RN_NA;
      break;
  }
  return _moduleType;
}
String rn2xx3::hweui()
{
  delay(100);
  while(_serial.available())
  {
    _serial.read();
  }
  _serial.println("sys get hweui");
  String addr = _serial.readStringUntil('\n');
  addr.trim();
  return addr;
}

String rn2xx3::sysver()
{
  delay(100);
  while(_serial.available())
    _serial.read();
  _serial.println("sys get ver");
  String ver = _serial.readStringUntil('\n');
  ver.trim();
  return ver;
}

bool rn2xx3::init()
{
  if(_appeui=="0")
  {
    return false;
  }
  else if(_otaa==true)
  {
    return init(_appeui, _appskey);
  }
  else
  {
    return init(_devAddr, _appskey, _nwkskey);
  }
}

bool rn2xx3::initOTAA(String AppEUI, String AppKey)
{
  return init(AppEUI, AppKey);
}

bool rn2xx3::init(String AppEUI, String AppKey)
{
  _otaa = true;
  _appeui = AppEUI;
  _nwkskey = "0";
  _appskey = AppKey; //reuse the variable
  String receivedData;

  //clear serial buffer
  while(_serial.available())
    _serial.read();

  _serial.println("sys get hweui");
  String addr = _serial.readStringUntil('\n');
  addr.trim();

  configureModuleType();

  switch (_moduleType) {
    case RN2903:
      _serial.println("mac reset");
      break;
    case RN2483:
      _serial.println("mac reset 868");
      break;
    default:
      // we shouldn't go forward with the init
      return false;
  }
  receivedData = _serial.readStringUntil('\n');

  _serial.println("mac set appeui "+_appeui);
  receivedData = _serial.readStringUntil('\n');

  _serial.println("mac set appkey "+_appskey);
  receivedData = _serial.readStringUntil('\n');

  if(addr!="" && addr.length() == 16)
  {
    _serial.println("mac set deveui "+addr);
  }
  else
  {
    _serial.println("mac set deveui "+_default_deveui);
  }
  receivedData = _serial.readStringUntil('\n');

  if (_moduleType == RN2903)
  {
    _serial.println("mac set pwridx 5");
  }
  else
  {
    _serial.println("mac set pwridx 1");
  }
  receivedData = _serial.readStringUntil('\n');

  _serial.println("mac set adr off");
  receivedData = _serial.readStringUntil('\n');

  if (_moduleType == RN2483)
  {
    _serial.println("mac set rx2 3 869525000");
    receivedData = _serial.readStringUntil('\n');
  }

  _serial.setTimeout(30000);
  _serial.println("mac save");
  receivedData = _serial.readStringUntil('\n');

  bool joined = false;

  for(int i=0; i<2 && !joined; i++)
  {
    _serial.println("mac join otaa");
    receivedData = _serial.readStringUntil('\n');
    receivedData = _serial.readStringUntil('\n');

    if(receivedData.startsWith("accepted"))
    {
      joined=true;
      delay(1000);
    }
    else
    {
      delay(1000);
    }
  }
  _serial.setTimeout(2000);
  return joined;
}

bool rn2xx3::initABP(String devAddr, String AppSKey, String NwkSKey)
{
  return init(devAddr, AppSKey, NwkSKey);
}

bool rn2xx3::init(String devAddr, String AppSKey, String NwkSKey)
{
  _otaa = false;
  _devAddr = devAddr;
  _appskey = AppSKey;
  _nwkskey = NwkSKey;
  String receivedData;

  //clear serial buffer
  while(_serial.available())
    _serial.read();

  configureModuleType();

  switch (_moduleType) {
    case RN2903:
      _serial.println("mac reset");
      _serial.readStringUntil('\n');
      break;
    case RN2483:
      _serial.println("mac reset 868");
      _serial.readStringUntil('\n');
      _serial.println("mac set rx2 3 869525000");
      _serial.readStringUntil('\n');
      break;
    default:
      // we shouldn't go forward with the init
      return false;
  }

  _serial.println("mac set nwkskey "+_nwkskey);
  _serial.readStringUntil('\n');
  _serial.println("mac set appskey "+_appskey);
  _serial.readStringUntil('\n');

  _serial.println("mac set devaddr "+_devAddr);
  _serial.readStringUntil('\n');

  _serial.println("mac set adr off");
  _serial.readStringUntil('\n');
  _serial.println("mac set ar off");
  _serial.readStringUntil('\n');

  if (_moduleType == RN2903)
  {
    _serial.println("mac set pwridx 5");
  }
  else
  {
    _serial.println("mac set pwridx 1");
  }
  _serial.readStringUntil('\n');
  _serial.println("mac set dr 5"); //0= min, 7=max
  _serial.readStringUntil('\n');

  _serial.setTimeout(60000);
  _serial.println("mac save");
  _serial.readStringUntil('\n');
  _serial.println("mac join abp");
  receivedData = _serial.readStringUntil('\n');
  receivedData = _serial.readStringUntil('\n');

  _serial.setTimeout(2000);
  delay(1000);

  if(receivedData.startsWith("accepted"))
  {
    return true;
    //with abp we can always join successfully as long as the keys are valid
  }
  else
  {
    return false;
  }
}

void rn2xx3::tx(String data)
{
  txUncnf(data); //we are unsure which mode we're in. Better not to wait for acks.
}

void rn2xx3::txCnf(String data)
{
  txData("mac tx cnf 1 ", data, true);
}

void rn2xx3::txUncnf(String data)
{
  txData("mac tx uncnf 1 ", data, true);
}

void rn2xx3::txData(String data, bool shouldEncode)
{
  txData("mac tx uncnf 1 ", data, shouldEncode);
}

bool rn2xx3::txData(String command, String data, bool shouldEncode)
{
  bool send_success = false;
  uint8_t busy_count = 0;
  uint8_t retry_count = 0;

  //clear serial buffer
  while(_serial.available())
    _serial.read();

  while(!send_success)
  {
    //retransmit a maximum of 10 times
    retry_count++;
    if(retry_count>10)
    {
      return false;
    }

    _serial.print(command);
    if(shouldEncode)
    {
      sendEncoded(data);
    }
    else
    {
      _serial.print(data);
    }
    _serial.println();
    String receivedData = _serial.readStringUntil('\n');

    if(receivedData.startsWith("ok"))
    {
      _serial.setTimeout(30000);
      receivedData = _serial.readStringUntil('\n');
      _serial.setTimeout(2000);

      if(receivedData.startsWith("mac_tx_ok"))
      {
        //SUCCESS!!
        send_success = true;
        return true;
      }

      else if(receivedData.startsWith("mac_rx"))
      {
        //we received data downstream
        //TODO: handle received data -
        // this can be done by returning a struct containing:
        // 1. a boolean for confirmed message acks'
        // 2. a boolean for received data
        // 3. a string/char array for the downlink data
        send_success = true;
        return true;
      }

      else if(receivedData.startsWith("mac_err"))
      {
        init();
      }

      else if(receivedData.startsWith("invalid_data_len"))
      {
        //this should never happen if the prototype worked
        send_success = true;
        return false;
      }

      else if(receivedData.startsWith("radio_tx_ok"))
      {
        //SUCCESS!!
        send_success = true;
        return true;
      }

      else if(receivedData.startsWith("radio_err"))
      {
        //This should never happen. If it does, something major is wrong.
        init();
      }

      else
      {
        //unknown response
        //init();
      }
    }

    else if(receivedData.startsWith("invalid_param"))
    {
      //should not happen if we typed the commands correctly
      send_success = true;
      return false;
    }

    else if(receivedData.startsWith("not_joined"))
    {
      init();
    }

    else if(receivedData.startsWith("no_free_ch"))
    {
      //retry
      delay(1000);
    }

    else if(receivedData.startsWith("silent"))
    {
      init();
    }

    else if(receivedData.startsWith("frame_counter_err_rejoin_needed"))
    {
      init();
    }

    else if(receivedData.startsWith("busy"))
    {
      busy_count++;

      if(busy_count>=10)
      {
        init();
      }
      else
      {
        delay(1000);
      }
    }

    else if(receivedData.startsWith("mac_paused"))
    {
      init();
    }

    else if(receivedData.startsWith("invalid_data_len"))
    {
      //should not happen if the prototype worked
      send_success = true;
      return false;
    }

    else
    {
      //unknown response after mac tx command
      init();
    }
  }

  return false; //should never reach this
}

void rn2xx3::sendEncoded(String input)
{
  char working;
  char buffer[3];
  for (unsigned i=0; i<input.length(); i++)
  {
    working = input.charAt(i);
    sprintf(buffer, "%02x", int(working));
    _serial.print(buffer);
  }
}

String rn2xx3::base16encode(String input)
{
  char charsOut[input.length()*2+1];
  char charsIn[input.length()+1];
  input.trim();
  input.toCharArray(charsIn, input.length()+1);

  unsigned i = 0;
  for(i = 0; i<input.length()+1; i++)
  {
    if(charsIn[i] == '\0') break;

    int value = int(charsIn[i]);

    char buffer[3];
    sprintf(buffer, "%02x", value);
    charsOut[2*i] = buffer[0];
    charsOut[2*i+1] = buffer[1];
  }
  charsOut[2*i] = '\0';
  String toReturn = String(charsOut);
  return toReturn;
}

String rn2xx3::base16decode(String input)
{
  char charsIn[input.length()+1];
  char charsOut[input.length()/2+1];
  input.trim();
  input.toCharArray(charsIn, input.length()+1);

  unsigned i = 0;
  for(i = 0; i<input.length()/2+1; i++)
  {
    if(charsIn[i*2] == '\0') break;
    if(charsIn[i*2+1] == '\0') break;

    char toDo[2];
    toDo[0] = charsIn[i*2];
    toDo[1] = charsIn[i*2+1];
    int out = strtoul(toDo, 0, 16);

    if(out<128)
    {
      charsOut[i] = char(out);
    }
  }
  charsOut[i] = '\0';
  return charsOut;
}

void rn2xx3::setDR(int dr)
{
  if(dr>=0 && dr<=5)
  {
    delay(100);
    while(_serial.available())
      _serial.read();
    _serial.print("mac set dr ");
    _serial.println(dr);
    _serial.readStringUntil('\n');
  }
}

void rn2xx3::sleep(long msec)
{
  _serial.print("sys sleep ");
  _serial.println(msec);
}

String rn2xx3::sendRawCommand(String command)
{
  delay(100);
  while(_serial.available())
    _serial.read();
  _serial.println(command);
  String ret = _serial.readStringUntil('\n');
  ret.trim();
  return ret;
}
<|endoftext|>


<commit_before>#include "md5mesh.h"
#include "base/lexer.h"
#include <string.h>

namespace base {
namespace opengl {

math::Vector3 Md5Joint::translate(const math::Vector3& v) const
{
    return orient.RotatePoint(v) + pos;
}

void readVector(Lexer& reader, math::Vector3& vec)
{
    vec.x = reader.ReadFloat();
    vec.y = reader.ReadFloat();
    vec.z = reader.ReadFloat();
}

void readQuat(Lexer& reader, math::Quat& q)
{
    q.x = reader.ReadFloat();
    q.y = reader.ReadFloat();
    q.z = reader.ReadFloat();
}

Entity* Entity::Load(const string& filename)
{
    Lexer reader(filename);
    u32 currentMeshIndex = 0;

    Entity* entity = new Entity;

    Md5Model& model = entity->object.md5Model;
    while(reader.HasMoreData())
    {
        reader.ReadToken();

        if (strcmp(reader.CurrentToken(), "MD5Version") == 0)
        {
            u32 version = (u32) reader.ReadFloat();
            if ( version!=10 )
            {
                return NULL;
            }
        }
        else if (strcmp(reader.CurrentToken(), "numJoints") == 0)
        {
            model.num_joints = (u32) reader.ReadFloat();
            if (model.num_joints > 0)
            {
                model.baseSkel = new Md5Joint[model.num_joints];
            }
        }
        else if (strcmp(reader.CurrentToken(), "numMeshes") == 0)
        {
            model.num_meshes = (u32) reader.ReadFloat();
            if (model.num_meshes > 0)
            {
                model.meshes = new Md5Mesh[model.num_meshes];
            }
        }
        else if (strcmp(reader.CurrentToken(), "joints") == 0)
        {
            reader.ReadToken(); // {

            for (i32 i = 0; i < model.num_joints; ++i)
            {
                Md5Joint& joint = model.baseSkel[i];

                //"name parent ( pos.x pos.y pos.z ) ( q.x q.y q.z )"
                joint.name = reader.ReadToken();
                joint.parent = (i32)reader.ReadFloat();

                reader.ReadToken(); // (
                readVector(reader, joint.pos);
                reader.ReadToken(); // )

                reader.ReadToken(); // (
                readQuat(reader, joint.orient);
                reader.ReadToken(); // )

                joint.orient.ComputeW();
            }

            reader.ReadToken(); // }
        }
        else if (strcmp(reader.CurrentToken(), "mesh") == 0)
        {
            reader.ReadToken(); // {
            Md5Mesh &mesh  = model.meshes[currentMeshIndex];
            while (strcmp(reader.CurrentToken(), "}") != 0 && reader.HasMoreData())
            {
                reader.ReadToken();
                if (strcmp(reader.CurrentToken(), "shader") == 0)
                {
                    mesh.shader = reader.ReadToken();
                }
                else if (strcmp(reader.CurrentToken(), "numverts") == 0)
                {
                    mesh.num_verts = (u32) reader.ReadFloat();
                    if ( mesh.num_verts > 0)
                    {
                        mesh.vertices    = new Md5Vertex [mesh.num_verts];
                        mesh.vertexArray = new Vertex[mesh.num_verts];
                    }
                }
                else if (strcmp(reader.CurrentToken(), "numtris") == 0)
                {
                     mesh.num_tris = (u32) reader.ReadFloat();
                    if ( mesh.num_tris > 0)
                    {
                        mesh.vertexIndices = new Face[mesh.num_tris];
                        mesh.triangles     = new Md5Triangle [mesh.num_tris];
                    }
                }
                else if (strcmp(reader.CurrentToken(), "numweights") == 0)
                {
                    mesh.num_weights = (u32) reader.ReadFloat();
                    if ( mesh.num_weights > 0)
                    {
                        mesh.weights = new Md5Weight [mesh.num_weights];
                    }
                }
                else if (strcmp(reader.CurrentToken(), "vert") == 0)
                {
                    //vert %d ( %f %f ) %d %d
                    u32 vertIndex = (u32) reader.ReadFloat();
                    reader.ReadToken();//(

                    Md5Vertex &vertex = mesh.vertices[vertIndex];
                    vertex.st.x = reader.ReadFloat();
                    vertex.st.y = reader.ReadFloat();

                    reader.ReadToken();//)

                    vertex.start = (u32) reader.ReadFloat();
                    vertex.count = (u32) reader.ReadFloat();

                }
                else if (strcmp(reader.CurrentToken(), "tri") == 0)
                {
                    // tri %d %d %d %d
                    u32 triangleIndex = (u32) reader.ReadFloat();
                    Md5Triangle &triangle = mesh.triangles[triangleIndex];

                    triangle.index[0] = (u32) reader.ReadFloat();
                    triangle.index[1] = (u32) reader.ReadFloat();
                    triangle.index[2] = (u32) reader.ReadFloat();
                }
                else if (strcmp(reader.CurrentToken(), "weight") == 0)
                {
                    //weight %d %d %f ( %f %f %f )
                    u32 weightIndex = (u32) reader.ReadFloat();
                    Md5Weight &weight = mesh.weights[weightIndex];

                    weight.joint = (u32) reader.ReadFloat();
                    weight.bias  = reader.ReadFloat();

                    reader.ReadToken(); //(
                    readVector(reader, weight.pos);
                    reader.ReadToken(); //)

                }
            }
            currentMeshIndex++;
        }
    }

    return entity;
}

void Entity::GenerateGPUVertices(Md5Mesh &mesh, const Md5Joint* skeleton)
{

    Vertex* currentVertex = mesh.vertexArray;
    for (int i = 0; i < mesh.num_verts; ++i)
    {
        currentVertex->tex = mesh.vertices[i].st;

        currentVertex->pos.set(0.0f);
        currentVertex->n.set(0.0f);
        currentVertex->tangent.set(0.0f);

        for (int j = 0; j < mesh.vertices[i].count; j++)
        {
            const Md5Weight& weight = mesh.weights[mesh.vertices[i].start + j];
            const Md5Joint& joint = skeleton[weight.joint];

            currentVertex->pos += joint.translate(weight.pos) * weight.bias;
            currentVertex->n += joint.orient.RotatePoint(weight.normal);
            currentVertex->tangent += joint.orient.RotatePoint(weight.tangent);
        }

        currentVertex->n.Normalize();
        currentVertex->tangent.Normalize();

        currentVertex++;
    }

    for (int i = 0; i<mesh.num_tris; i++)
    {
        for (int j=0; j<3; j++)
        {
            mesh.vertexIndices[i].index[j] = (u16)mesh.triangles[i].index[j];
        }
    }

    GenerateLightningInfo(mesh);
}

void Entity::GenerateLightningInfo(Md5Mesh &mesh)
{
    for ( u32 i = 0; i < mesh.num_tris; i++)
    {
        f32 d0[5], d1[5];
        Vertex* a;
        Vertex* b;
        Vertex* c;

        math::Vector3 temp, normal, tangents[2];

        a = mesh.vertexArray + mesh.triangles[i].index[0];
        b = mesh.vertexArray + mesh.triangles[i].index[1];
        c = mesh.vertexArray + mesh.triangles[i].index[2];

        d0[0] = b->pos.x - a->pos.x;
        d0[1] = b->pos.y - a->pos.y;
        d0[2] = b->pos.z - a->pos.z;
        d0[3] = b->tex.x - a->tex.x;
        d0[4] = b->tex.y - a->tex.y;

        d1[0] = c->pos.x - a->pos.x;
        d1[1] = c->pos.y - a->pos.y;
        d1[2] = c->pos.z - a->pos.z;
        d1[3] = c->tex.x - a->tex.x;
        d1[4] = c->tex.y - a->tex.y;

        normal = Vector3(
            d1[1] * d0[2] - d1[2] * d0[1],
            d1[2] * d0[0] - d1[0] * d0[2],
            d1[0] * d0[1] - d1[1] * d0[0]
        );
        normal.Normalize();

        tangents[0] = Vector3(
            d0[0] * d1[4] - d0[4] * d1[0],
            d0[1] * d1[4] - d0[4] * d1[1],
            d0[2] * d1[4] - d0[4] * d1[2]
        );
        tangents[0].Normalize();

        tangents[1] = Vector3(
            d0[3] * d1[0] - d0[0] * d1[3],
            d0[3] * d1[1] - d0[1] * d1[3],
            d0[3] * d1[2] - d0[2] * d1[3]
        );
        tangents[1].Normalize();

        for (int j=0;j<3; j++) {
            Vertex* v = mesh.vertexArray + mesh.triangles[i].index[j];
            v->n += normal;
            v->tangent  += tangents[0];
            v->binormal += tangents[1];
        }
    }
    for (u32 i=0;i<mesh.num_verts;i++)
    {
        mesh.vertexArray[i].n.Normalize();
        f32 d = Dot(mesh.vertexArray[i].tangent, mesh.vertexArray[i].n);
        mesh.vertexArray[i].tangent = mesh.vertexArray[i].tangent - mesh.vertexArray[i].n * d;
        mesh.vertexArray[i].tangent.Normalize();
        d = Dot(mesh.vertexArray[i].binormal, mesh.vertexArray[i].n);
        mesh.vertexArray[i].binormal = mesh.vertexArray[i].binormal - mesh.vertexArray[i].n * d;
        mesh.vertexArray[i].binormal.Normalize();
    }
}

}
}
<commit_msg>Several Visual Studio complier warnings solved<commit_after>#include "md5mesh.h"
#include "base/lexer.h"
#include <string.h>

namespace base {
namespace opengl {

math::Vector3 Md5Joint::translate(const math::Vector3& v) const
{
    return orient.RotatePoint(v) + pos;
}

void readVector(Lexer& reader, math::Vector3& vec)
{
    vec.x = reader.ReadFloat();
    vec.y = reader.ReadFloat();
    vec.z = reader.ReadFloat();
}

void readQuat(Lexer& reader, math::Quat& q)
{
    q.x = reader.ReadFloat();
    q.y = reader.ReadFloat();
    q.z = reader.ReadFloat();
}

Entity* Entity::Load(const string& filename)
{
    Lexer reader(filename);
    u32 currentMeshIndex = 0;

    Entity* entity = new Entity;

    Md5Model& model = entity->object.md5Model;
    while(reader.HasMoreData())
    {
        reader.ReadToken();

        if (strcmp(reader.CurrentToken(), "MD5Version") == 0)
        {
            u32 version = (u32) reader.ReadFloat();
            if ( version!=10 )
            {
                return NULL;
            }
        }
        else if (strcmp(reader.CurrentToken(), "numJoints") == 0)
        {
            model.num_joints = (u32) reader.ReadFloat();
            if (model.num_joints > 0)
            {
                model.baseSkel = new Md5Joint[model.num_joints];
            }
        }
        else if (strcmp(reader.CurrentToken(), "numMeshes") == 0)
        {
            model.num_meshes = (u32) reader.ReadFloat();
            if (model.num_meshes > 0)
            {
                model.meshes = new Md5Mesh[model.num_meshes];
            }
        }
        else if (strcmp(reader.CurrentToken(), "joints") == 0)
        {
            reader.ReadToken(); // {

            for (i32 i = 0; i < model.num_joints; ++i)
            {
                Md5Joint& joint = model.baseSkel[i];

                //"name parent ( pos.x pos.y pos.z ) ( q.x q.y q.z )"
                joint.name = reader.ReadToken();
                joint.parent = (i32)reader.ReadFloat();

                reader.ReadToken(); // (
                readVector(reader, joint.pos);
                reader.ReadToken(); // )

                reader.ReadToken(); // (
                readQuat(reader, joint.orient);
                reader.ReadToken(); // )

                joint.orient.ComputeW();
            }

            reader.ReadToken(); // }
        }
        else if (strcmp(reader.CurrentToken(), "mesh") == 0)
        {
            reader.ReadToken(); // {
            Md5Mesh &mesh  = model.meshes[currentMeshIndex];
            while (strcmp(reader.CurrentToken(), "}") != 0 && reader.HasMoreData())
            {
                reader.ReadToken();
                if (strcmp(reader.CurrentToken(), "shader") == 0)
                {
                    mesh.shader = reader.ReadToken();
                }
                else if (strcmp(reader.CurrentToken(), "numverts") == 0)
                {
                    mesh.num_verts = (u32) reader.ReadFloat();
                    if ( mesh.num_verts > 0)
                    {
                        mesh.vertices    = new Md5Vertex [mesh.num_verts];
                        mesh.vertexArray = new Vertex[mesh.num_verts];
                    }
                }
                else if (strcmp(reader.CurrentToken(), "numtris") == 0)
                {
                     mesh.num_tris = (u32) reader.ReadFloat();
                    if ( mesh.num_tris > 0)
                    {
                        mesh.vertexIndices = new Face[mesh.num_tris];
                        mesh.triangles     = new Md5Triangle [mesh.num_tris];
                    }
                }
                else if (strcmp(reader.CurrentToken(), "numweights") == 0)
                {
                    mesh.num_weights = (u32) reader.ReadFloat();
                    if ( mesh.num_weights > 0)
                    {
                        mesh.weights = new Md5Weight [mesh.num_weights];
                    }
                }
                else if (strcmp(reader.CurrentToken(), "vert") == 0)
                {
                    //vert %d ( %f %f ) %d %d
                    u32 vertIndex = (u32) reader.ReadFloat();
                    reader.ReadToken();//(

                    Md5Vertex &vertex = mesh.vertices[vertIndex];
                    vertex.st.x = reader.ReadFloat();
                    vertex.st.y = reader.ReadFloat();

                    reader.ReadToken();//)

                    vertex.start = (u32) reader.ReadFloat();
                    vertex.count = (u32) reader.ReadFloat();

                }
                else if (strcmp(reader.CurrentToken(), "tri") == 0)
                {
                    // tri %d %d %d %d
                    u32 triangleIndex = (u32) reader.ReadFloat();
                    Md5Triangle &triangle = mesh.triangles[triangleIndex];

                    triangle.index[0] = (u32) reader.ReadFloat();
                    triangle.index[1] = (u32) reader.ReadFloat();
                    triangle.index[2] = (u32) reader.ReadFloat();
                }
                else if (strcmp(reader.CurrentToken(), "weight") == 0)
                {
                    //weight %d %d %f ( %f %f %f )
                    u32 weightIndex = (u32) reader.ReadFloat();
                    Md5Weight &weight = mesh.weights[weightIndex];

                    weight.joint = (u32) reader.ReadFloat();
                    weight.bias  = reader.ReadFloat();

                    reader.ReadToken(); //(
                    readVector(reader, weight.pos);
                    reader.ReadToken(); //)

                }
            }
            currentMeshIndex++;
        }
    }

    return entity;
}

void Entity::GenerateGPUVertices(Md5Mesh &mesh, const Md5Joint* skeleton)
{

    Vertex* currentVertex = mesh.vertexArray;
    for (i32 i = 0; i < mesh.num_verts; ++i)
    {
        currentVertex->tex = mesh.vertices[i].st;

        currentVertex->pos.set(0.0f);
        currentVertex->n.set(0.0f);
        currentVertex->tangent.set(0.0f);

        for (u32 j = 0; j < mesh.vertices[i].count; j++)
        {
            const Md5Weight& weight = mesh.weights[mesh.vertices[i].start + j];
            const Md5Joint& joint = skeleton[weight.joint];

            currentVertex->pos += joint.translate(weight.pos) * weight.bias;
            currentVertex->n += joint.orient.RotatePoint(weight.normal);
            currentVertex->tangent += joint.orient.RotatePoint(weight.tangent);
        }

        currentVertex->n.Normalize();
        currentVertex->tangent.Normalize();

        currentVertex++;
    }

    for (int i = 0; i<mesh.num_tris; i++)
    {
        for (int j=0; j<3; j++)
        {
            mesh.vertexIndices[i].index[j] = (u16)mesh.triangles[i].index[j];
        }
    }

    GenerateLightningInfo(mesh);
}

void Entity::GenerateLightningInfo(Md5Mesh &mesh)
{
    for ( i32 i = 0; i < mesh.num_tris; i++)
    {
        f32 d0[5], d1[5];
        Vertex* a;
        Vertex* b;
        Vertex* c;

        math::Vector3 temp, normal, tangents[2];

        a = mesh.vertexArray + mesh.triangles[i].index[0];
        b = mesh.vertexArray + mesh.triangles[i].index[1];
        c = mesh.vertexArray + mesh.triangles[i].index[2];

        d0[0] = b->pos.x - a->pos.x;
        d0[1] = b->pos.y - a->pos.y;
        d0[2] = b->pos.z - a->pos.z;
        d0[3] = b->tex.x - a->tex.x;
        d0[4] = b->tex.y - a->tex.y;

        d1[0] = c->pos.x - a->pos.x;
        d1[1] = c->pos.y - a->pos.y;
        d1[2] = c->pos.z - a->pos.z;
        d1[3] = c->tex.x - a->tex.x;
        d1[4] = c->tex.y - a->tex.y;

        normal = Vector3(
            d1[1] * d0[2] - d1[2] * d0[1],
            d1[2] * d0[0] - d1[0] * d0[2],
            d1[0] * d0[1] - d1[1] * d0[0]
        );
        normal.Normalize();

        tangents[0] = Vector3(
            d0[0] * d1[4] - d0[4] * d1[0],
            d0[1] * d1[4] - d0[4] * d1[1],
            d0[2] * d1[4] - d0[4] * d1[2]
        );
        tangents[0].Normalize();

        tangents[1] = Vector3(
            d0[3] * d1[0] - d0[0] * d1[3],
            d0[3] * d1[1] - d0[1] * d1[3],
            d0[3] * d1[2] - d0[2] * d1[3]
        );
        tangents[1].Normalize();

        for (int j=0;j<3; j++) {
            Vertex* v = mesh.vertexArray + mesh.triangles[i].index[j];
            v->n += normal;
            v->tangent  += tangents[0];
            v->binormal += tangents[1];
        }
    }
    for (i32 i=0;i<mesh.num_verts;i++)
    {
        mesh.vertexArray[i].n.Normalize();
        f32 d = Dot(mesh.vertexArray[i].tangent, mesh.vertexArray[i].n);
        mesh.vertexArray[i].tangent = mesh.vertexArray[i].tangent - mesh.vertexArray[i].n * d;
        mesh.vertexArray[i].tangent.Normalize();
        d = Dot(mesh.vertexArray[i].binormal, mesh.vertexArray[i].n);
        mesh.vertexArray[i].binormal = mesh.vertexArray[i].binormal - mesh.vertexArray[i].n * d;
        mesh.vertexArray[i].binormal.Normalize();
    }
}

}
}
<|endoftext|>


<commit_before>//
//  StaticAnalyser.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 15/09/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../Disassembler/Disassembler6502.hpp"

using namespace StaticAnalyser::Atari;

static void DeterminePagingFor2kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment)
{
	// if this is a 2kb cartridge then it's definitely either unpaged or a CommaVid
	uint16_t entry_address, break_address;

	entry_address = ((uint16_t)(segment.data[0x7fc] | (segment.data[0x7fd] << 8))) & 0x1fff;
	break_address = ((uint16_t)(segment.data[0x7fe] | (segment.data[0x7ff] << 8))) & 0x1fff;

	// a CommaVid start address needs to be outside of its RAM
	if(entry_address < 0x1800 || break_address < 0x1800) return;

	std::function<size_t(uint16_t address)> high_location_mapper = [](uint16_t address) {
		address &= 0x1fff;
		return (size_t)(address - 0x1800);
	};
	std::function<size_t(uint16_t address)> full_range_mapper = [](uint16_t address) {
		if(!(address & 0x1000)) return (size_t)-1;
		return (size_t)(address & 0x7ff);
	};

	StaticAnalyser::MOS6502::Disassembly high_location_disassembly =
		StaticAnalyser::MOS6502::Disassemble(segment.data, high_location_mapper, {entry_address, break_address});

	// if there are no subroutines in the top 2kb of memory then this isn't a CommaVid
	bool has_appropriate_subroutine_calls = false;
	bool has_inappropriate_subroutine_calls = false;
	for(uint16_t address : high_location_disassembly.internal_calls)
	{
		const uint16_t masked_address = address & 0x1fff;
		has_appropriate_subroutine_calls |= (masked_address >= 0x1800);
		has_inappropriate_subroutine_calls |= (masked_address < 0x1800);
	}

	// assumption here: a CommaVid will never branch into RAM. Possibly unsafe: if it won't then what's the RAM for?
	if(!has_appropriate_subroutine_calls || has_inappropriate_subroutine_calls) return;

	std::set<uint16_t> all_writes = high_location_disassembly.external_stores;
	all_writes.insert(high_location_disassembly.external_modifies.begin(), high_location_disassembly.external_modifies.end());

	// a CommaVid will use its RAM
	if(all_writes.empty()) return;

	bool has_appropriate_accesses = false;
	for(uint16_t address : all_writes)
	{
		const uint16_t masked_address = address & 0x1fff;
		if(masked_address >= 0x1400 && masked_address < 0x1800)
		{
			has_appropriate_accesses = true;
			break;
		}
	}

	// in desperation, accept any kind of store that looks likely to be intended for large amounts of memory
	bool has_wide_area_store = false;
	if(!has_appropriate_accesses)
	{
		for(std::map<uint16_t, StaticAnalyser::MOS6502::Instruction>::value_type &entry : high_location_disassembly.instructions_by_address)
		{
			if(entry.second.operation == StaticAnalyser::MOS6502::Instruction::STA)
			{
				has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::Indirect;
				has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::IndexedIndirectX;
				has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::IndirectIndexedY;
			}
		}
	}

	// conclude that this is a CommaVid if it attempted to write something to the CommaVid RAM locations;
	// caveat: false positives aren't likely to be problematic; a false positive is a 2KB ROM that always addresses
	// itself so as to land in ROM even if mapped as a CommaVid and this code is on the fence as to whether it
	// attempts to modify itself but it probably doesn't
	if(has_appropriate_accesses || has_wide_area_store)
		target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CommaVid;
}

static void DeterminePagingFor8kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const StaticAnalyser::MOS6502::Disassembly &disassembly)
{
	// Activision stack titles have their vectors at the top of the low 4k, not the top, and
	// always list 0xf000 as both vectors; they do not repeat them
	if(
		segment.data[4095] == 0xf0 && segment.data[4093] == 0xf0 && segment.data[4094] == 0x00 && segment.data[4092] == 0x00 &&
		(segment.data[8191] != 0xf0 || segment.data[8189] != 0xf0 || segment.data[8190] != 0x00 || segment.data[8188] != 0x00)
	)
	{
		target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::ActivisionStack;
		return;
	}

	// make an assumption that this is the Atari paging model
	target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Atari8k;

	std::set<uint16_t> internal_accesses;
	internal_accesses.insert(disassembly.internal_stores.begin(), disassembly.internal_stores.end());
	internal_accesses.insert(disassembly.internal_modifies.begin(), disassembly.internal_modifies.end());
	internal_accesses.insert(disassembly.internal_loads.begin(), disassembly.internal_loads.end());

	int atari_access_count = 0;
	int parker_access_count = 0;
	int tigervision_access_count = 0;
	for(uint16_t address : internal_accesses)
	{
		uint16_t masked_address = address & 0x1fff;
		atari_access_count += masked_address >= 0x1ff8 && masked_address < 0x1ffa;
		parker_access_count += masked_address >= 0x1fe0 && masked_address < 0x1ff8;
	}
	for(uint16_t address: disassembly.external_stores)
	{
		uint16_t masked_address = address & 0x1fff;
		tigervision_access_count += masked_address == 0x3f;
	}

	if(parker_access_count > atari_access_count) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::ParkerBros;
	else if(tigervision_access_count > atari_access_count) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Tigervision;
}

static void DeterminePagingFor16kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const StaticAnalyser::MOS6502::Disassembly &disassembly)
{
	// make an assumption that this is the Atari paging model
	target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Atari16k;

	std::set<uint16_t> internal_accesses;
	internal_accesses.insert(disassembly.internal_stores.begin(), disassembly.internal_stores.end());
	internal_accesses.insert(disassembly.internal_modifies.begin(), disassembly.internal_modifies.end());
	internal_accesses.insert(disassembly.internal_loads.begin(), disassembly.internal_loads.end());

	int atari_access_count = 0;
	int mnetwork_access_count = 0;
	for(uint16_t address : internal_accesses)
	{
		uint16_t masked_address = address & 0x1fff;
		atari_access_count += masked_address >= 0x1ff6 && masked_address < 0x1ffa;
		mnetwork_access_count += masked_address >= 0x1fe0 && masked_address < 0x1ffb;
	}

	if(mnetwork_access_count > atari_access_count) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::MNetwork;
}

static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment)
{
	if(segment.data.size() == 2048)
	{
		DeterminePagingFor2kCartridge(target, segment);
		return;
	}

	uint16_t entry_address, break_address;

	entry_address = (uint16_t)(segment.data[segment.data.size() - 4] | (segment.data[segment.data.size() - 3] << 8));
	break_address = (uint16_t)(segment.data[segment.data.size() - 2] | (segment.data[segment.data.size() - 1] << 8));

	std::function<size_t(uint16_t address)> address_mapper = [](uint16_t address) {
		if(!(address & 0x1000)) return (size_t)-1;
		return (size_t)(address & 0xfff);
	};

	std::vector<uint8_t> final_4k(segment.data.end() - 4096, segment.data.end());
	StaticAnalyser::MOS6502::Disassembly disassembly = StaticAnalyser::MOS6502::Disassemble(final_4k, address_mapper, {entry_address, break_address});

	switch(segment.data.size())
	{
		case 8192:
			DeterminePagingFor8kCartridge(target, segment, disassembly);
		break;
		case 12288:
			target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus;
		break;
		case 16384:
			DeterminePagingFor16kCartridge(target, segment, disassembly);
		break;
		case 32768:
			target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Atari32k;
		break;
		default:
		break;
	}

	// check for a Super Chip. Atari ROM images [almost] always have the same value stored over RAM
	// regions; when they don't they at least seem to have the first 128 bytes be the same as the
	// next 128 bytes. So check for that.
	if(	target.atari.paging_model != StaticAnalyser::Atari2600PagingModel::CBSRamPlus &&
		target.atari.paging_model != StaticAnalyser::Atari2600PagingModel::MNetwork)
	{
		bool has_superchip = true;
		for(size_t address = 0; address < 128; address++)
		{
			if(segment.data[address] != segment.data[address+128])
			{
				has_superchip = false;
				break;
			}
		}
		target.atari.uses_superchip = has_superchip;
	}

	// check for a Tigervision or Tigervision-esque scheme
	if(target.atari.paging_model == StaticAnalyser::Atari2600PagingModel::None && segment.data.size() > 4096)
	{
		bool looks_like_tigervision = disassembly.external_stores.find(0x3f) != disassembly.external_stores.end();
		if(looks_like_tigervision) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Tigervision;
	}
}

void StaticAnalyser::Atari::AddTargets(
	const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
	const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
	const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
	std::list<StaticAnalyser::Target> &destination)
{
	// TODO: any sort of sanity checking at all; at the minute just trust the file type
	// approximation already performed.
	Target target;
	target.machine = Target::Atari2600;
	target.probability = 1.0;
	target.disks = disks;
	target.tapes = tapes;
	target.cartridges = cartridges;
	target.atari.paging_model = Atari2600PagingModel::None;
	target.atari.uses_superchip = false;

	// try to figure out the paging scheme
	if(!cartridges.empty())
	{
		const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridges.front()->get_segments();

		if(segments.size() == 1)
		{
			const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
			DeterminePagingForCartridge(target, segment);
		}
	}

	destination.push_back(target);
}
<commit_msg>'Perfected' the Activision stack paging detector.<commit_after>//
//  StaticAnalyser.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 15/09/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../Disassembler/Disassembler6502.hpp"

using namespace StaticAnalyser::Atari;

static void DeterminePagingFor2kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment)
{
	// if this is a 2kb cartridge then it's definitely either unpaged or a CommaVid
	uint16_t entry_address, break_address;

	entry_address = ((uint16_t)(segment.data[0x7fc] | (segment.data[0x7fd] << 8))) & 0x1fff;
	break_address = ((uint16_t)(segment.data[0x7fe] | (segment.data[0x7ff] << 8))) & 0x1fff;

	// a CommaVid start address needs to be outside of its RAM
	if(entry_address < 0x1800 || break_address < 0x1800) return;

	std::function<size_t(uint16_t address)> high_location_mapper = [](uint16_t address) {
		address &= 0x1fff;
		return (size_t)(address - 0x1800);
	};
	std::function<size_t(uint16_t address)> full_range_mapper = [](uint16_t address) {
		if(!(address & 0x1000)) return (size_t)-1;
		return (size_t)(address & 0x7ff);
	};

	StaticAnalyser::MOS6502::Disassembly high_location_disassembly =
		StaticAnalyser::MOS6502::Disassemble(segment.data, high_location_mapper, {entry_address, break_address});

	// if there are no subroutines in the top 2kb of memory then this isn't a CommaVid
	bool has_appropriate_subroutine_calls = false;
	bool has_inappropriate_subroutine_calls = false;
	for(uint16_t address : high_location_disassembly.internal_calls)
	{
		const uint16_t masked_address = address & 0x1fff;
		has_appropriate_subroutine_calls |= (masked_address >= 0x1800);
		has_inappropriate_subroutine_calls |= (masked_address < 0x1800);
	}

	// assumption here: a CommaVid will never branch into RAM. Possibly unsafe: if it won't then what's the RAM for?
	if(!has_appropriate_subroutine_calls || has_inappropriate_subroutine_calls) return;

	std::set<uint16_t> all_writes = high_location_disassembly.external_stores;
	all_writes.insert(high_location_disassembly.external_modifies.begin(), high_location_disassembly.external_modifies.end());

	// a CommaVid will use its RAM
	if(all_writes.empty()) return;

	bool has_appropriate_accesses = false;
	for(uint16_t address : all_writes)
	{
		const uint16_t masked_address = address & 0x1fff;
		if(masked_address >= 0x1400 && masked_address < 0x1800)
		{
			has_appropriate_accesses = true;
			break;
		}
	}

	// in desperation, accept any kind of store that looks likely to be intended for large amounts of memory
	bool has_wide_area_store = false;
	if(!has_appropriate_accesses)
	{
		for(std::map<uint16_t, StaticAnalyser::MOS6502::Instruction>::value_type &entry : high_location_disassembly.instructions_by_address)
		{
			if(entry.second.operation == StaticAnalyser::MOS6502::Instruction::STA)
			{
				has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::Indirect;
				has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::IndexedIndirectX;
				has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::IndirectIndexedY;
			}
		}
	}

	// conclude that this is a CommaVid if it attempted to write something to the CommaVid RAM locations;
	// caveat: false positives aren't likely to be problematic; a false positive is a 2KB ROM that always addresses
	// itself so as to land in ROM even if mapped as a CommaVid and this code is on the fence as to whether it
	// attempts to modify itself but it probably doesn't
	if(has_appropriate_accesses || has_wide_area_store)
		target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CommaVid;
}

static void DeterminePagingFor8kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const StaticAnalyser::MOS6502::Disassembly &disassembly)
{
	// Activision stack titles have their vectors at the top of the low 4k, not the top, and
	// always list 0xf000 as both vectors; they do not repeat them, and, inexplicably, they all
	// issue an SEI as their first instruction (maybe some sort of relic of the development environment?)
	if(
		segment.data[4095] == 0xf0 && segment.data[4093] == 0xf0 && segment.data[4094] == 0x00 && segment.data[4092] == 0x00 &&
		(segment.data[8191] != 0xf0 || segment.data[8189] != 0xf0 || segment.data[8190] != 0x00 || segment.data[8188] != 0x00) &&
		segment.data[0] == 0x78
	)
	{
		target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::ActivisionStack;
		return;
	}

	// make an assumption that this is the Atari paging model
	target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Atari8k;

	std::set<uint16_t> internal_accesses;
	internal_accesses.insert(disassembly.internal_stores.begin(), disassembly.internal_stores.end());
	internal_accesses.insert(disassembly.internal_modifies.begin(), disassembly.internal_modifies.end());
	internal_accesses.insert(disassembly.internal_loads.begin(), disassembly.internal_loads.end());

	int atari_access_count = 0;
	int parker_access_count = 0;
	int tigervision_access_count = 0;
	for(uint16_t address : internal_accesses)
	{
		uint16_t masked_address = address & 0x1fff;
		atari_access_count += masked_address >= 0x1ff8 && masked_address < 0x1ffa;
		parker_access_count += masked_address >= 0x1fe0 && masked_address < 0x1ff8;
	}
	for(uint16_t address: disassembly.external_stores)
	{
		uint16_t masked_address = address & 0x1fff;
		tigervision_access_count += masked_address == 0x3f;
	}

	if(parker_access_count > atari_access_count) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::ParkerBros;
	else if(tigervision_access_count > atari_access_count) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Tigervision;
}

static void DeterminePagingFor16kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const StaticAnalyser::MOS6502::Disassembly &disassembly)
{
	// make an assumption that this is the Atari paging model
	target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Atari16k;

	std::set<uint16_t> internal_accesses;
	internal_accesses.insert(disassembly.internal_stores.begin(), disassembly.internal_stores.end());
	internal_accesses.insert(disassembly.internal_modifies.begin(), disassembly.internal_modifies.end());
	internal_accesses.insert(disassembly.internal_loads.begin(), disassembly.internal_loads.end());

	int atari_access_count = 0;
	int mnetwork_access_count = 0;
	for(uint16_t address : internal_accesses)
	{
		uint16_t masked_address = address & 0x1fff;
		atari_access_count += masked_address >= 0x1ff6 && masked_address < 0x1ffa;
		mnetwork_access_count += masked_address >= 0x1fe0 && masked_address < 0x1ffb;
	}

	if(mnetwork_access_count > atari_access_count) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::MNetwork;
}

static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment)
{
	if(segment.data.size() == 2048)
	{
		DeterminePagingFor2kCartridge(target, segment);
		return;
	}

	uint16_t entry_address, break_address;

	entry_address = (uint16_t)(segment.data[segment.data.size() - 4] | (segment.data[segment.data.size() - 3] << 8));
	break_address = (uint16_t)(segment.data[segment.data.size() - 2] | (segment.data[segment.data.size() - 1] << 8));

	std::function<size_t(uint16_t address)> address_mapper = [](uint16_t address) {
		if(!(address & 0x1000)) return (size_t)-1;
		return (size_t)(address & 0xfff);
	};

	std::vector<uint8_t> final_4k(segment.data.end() - 4096, segment.data.end());
	StaticAnalyser::MOS6502::Disassembly disassembly = StaticAnalyser::MOS6502::Disassemble(final_4k, address_mapper, {entry_address, break_address});

	switch(segment.data.size())
	{
		case 8192:
			DeterminePagingFor8kCartridge(target, segment, disassembly);
		break;
		case 12288:
			target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus;
		break;
		case 16384:
			DeterminePagingFor16kCartridge(target, segment, disassembly);
		break;
		case 32768:
			target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Atari32k;
		break;
		default:
		break;
	}

	// check for a Super Chip. Atari ROM images [almost] always have the same value stored over RAM
	// regions; when they don't they at least seem to have the first 128 bytes be the same as the
	// next 128 bytes. So check for that.
	if(	target.atari.paging_model != StaticAnalyser::Atari2600PagingModel::CBSRamPlus &&
		target.atari.paging_model != StaticAnalyser::Atari2600PagingModel::MNetwork)
	{
		bool has_superchip = true;
		for(size_t address = 0; address < 128; address++)
		{
			if(segment.data[address] != segment.data[address+128])
			{
				has_superchip = false;
				break;
			}
		}
		target.atari.uses_superchip = has_superchip;
	}

	// check for a Tigervision or Tigervision-esque scheme
	if(target.atari.paging_model == StaticAnalyser::Atari2600PagingModel::None && segment.data.size() > 4096)
	{
		bool looks_like_tigervision = disassembly.external_stores.find(0x3f) != disassembly.external_stores.end();
		if(looks_like_tigervision) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Tigervision;
	}
}

void StaticAnalyser::Atari::AddTargets(
	const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
	const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
	const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
	std::list<StaticAnalyser::Target> &destination)
{
	// TODO: any sort of sanity checking at all; at the minute just trust the file type
	// approximation already performed.
	Target target;
	target.machine = Target::Atari2600;
	target.probability = 1.0;
	target.disks = disks;
	target.tapes = tapes;
	target.cartridges = cartridges;
	target.atari.paging_model = Atari2600PagingModel::None;
	target.atari.uses_superchip = false;

	// try to figure out the paging scheme
	if(!cartridges.empty())
	{
		const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridges.front()->get_segments();

		if(segments.size() == 1)
		{
			const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
			DeterminePagingForCartridge(target, segment);
		}
	}

	destination.push_back(target);
}
<|endoftext|>


<commit_before>#include "HalideRuntime.h"
#include "scoped_mutex_lock.h"

extern "C" {

struct _halide_runtime_internal_registered_filter_t {
    struct _halide_runtime_internal_registered_filter_t *next;
    const halide_filter_metadata_t* metadata;
    int (*argv_func)(void **args);
};

};

namespace Halide { namespace Runtime { namespace Internal {

struct list_head_t {
    halide_mutex mutex;
    _halide_runtime_internal_registered_filter_t *next;

    list_head_t() : mutex(), next(NULL) {}
};

static list_head_t* get_list_head() {
    static list_head_t head;
    return &head;
}

} } }

extern "C" {

// This is looked up by name in Codegen_LLVM, which is easier to do
// for functions with plain C linkage.
WEAK void halide_runtime_internal_register_metadata(_halide_runtime_internal_registered_filter_t *info) {
    // Note that although the metadata pointer itself is valid, the contents pointed
    // to by it may not be initialized yet (since order of execution is not guaranteed in this case);
    // it is essential that this code not do anything with that pointer other than store
    // it for future use. (The name argument will always be valid here, however.)
    list_head_t* head = get_list_head();
    ScopedMutexLock lock(&head->mutex);
    info->next = head->next;
    head->next = info;
}

WEAK int halide_enumerate_registered_filters(void *user_context, void* enumerate_context, enumerate_func_t func) {
    list_head_t* head = get_list_head();
    ScopedMutexLock lock(&head->mutex);
    for (_halide_runtime_internal_registered_filter_t* f = head->next; f != NULL; f = f->next) {
        int r = (*func)(enumerate_context, f->metadata, f->argv_func);
        if (r != 0) return r;
    }
    return 0;
}

}  // extern "C"
<commit_msg>Make metadata linked list a global to fix windows issue<commit_after>#include "HalideRuntime.h"
#include "scoped_mutex_lock.h"

extern "C" {

struct _halide_runtime_internal_registered_filter_t {
    struct _halide_runtime_internal_registered_filter_t *next;
    const halide_filter_metadata_t* metadata;
    int (*argv_func)(void **args);
};

};

namespace Halide { namespace Runtime { namespace Internal {

struct list_head_t {
    halide_mutex mutex;
    _halide_runtime_internal_registered_filter_t *next;
};

WEAK list_head_t list_head;

} } }

extern "C" {

// This is looked up by name in Codegen_LLVM, which is easier to do
// for functions with plain C linkage.
WEAK void halide_runtime_internal_register_metadata(_halide_runtime_internal_registered_filter_t *info) {
    // Note that although the metadata pointer itself is valid, the contents pointed
    // to by it may not be initialized yet (since order of execution is not guaranteed in this case);
    // it is essential that this code not do anything with that pointer other than store
    // it for future use. (The name argument will always be valid here, however.)
    ScopedMutexLock lock(&list_head.mutex);
    info->next = list_head.next;
    list_head.next = info;
}

WEAK int halide_enumerate_registered_filters(void *user_context, void* enumerate_context, enumerate_func_t func) {
    ScopedMutexLock lock(&list_head.mutex);
    for (_halide_runtime_internal_registered_filter_t* f = list_head.next; f != NULL; f = f->next) {
        int r = (*func)(enumerate_context, f->metadata, f->argv_func);
        if (r != 0) return r;
    }
    return 0;
}

}  // extern "C"
<|endoftext|>