<commit_before>#include <mtp/ptp/Device.h>
#include <mtp/ptp/Response.h>
#include <mtp/ptp/Container.h>
#include <mtp/ptp/Messages.h>
#include <mtp/usb/Context.h>
#include <mtp/ptp/OperationRequest.h>

namespace mtp
{

	msg::DeviceInfo Device::GetDeviceInfo()
	{
		OperationRequest req(OperationCode::GetDeviceInfo, 0);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(data, response);
		//HexDump("payload", data);

		InputStream stream(data, 8); //operation code + session id
		msg::DeviceInfo gdi;
		gdi.Read(stream);
		return gdi;
	}

	SessionPtr Device::OpenSession(u32 sessionId)
	{
		OperationRequest req(OperationCode::OpenSession, 0, sessionId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(data, response);
		//HexDump("payload", data);

		return std::make_shared<Session>(_packeter.GetPipe(), sessionId);
	}

	void PipePacketer::Write(const ByteArray &data, int timeout)
	{
		//HexDump("send", data);
		_pipe->Write(data, timeout);
	}

	ByteArray PipePacketer::ReadMessage(int timeout)
	{
		ByteArray result;
		u32 size = ~0u;
		size_t offset = 0;
		size_t packet_offset;
		while(true)
		{
			ByteArray data = _pipe->Read(timeout);
			if (size == ~0u)
			{
				InputStream stream(data);
				stream >> size;
				printf("DATA SIZE = %u\n", size);
				if (size < 4)
					throw std::runtime_error("invalid size");
				packet_offset = 4;
				result.resize(size - 4);
			}
			else
				packet_offset = 0;
			//HexDump("recv", data);

			size_t src_n = std::min(data.size() - packet_offset, result.size() - offset);
			std::copy(data.begin() + packet_offset, data.begin() + packet_offset + src_n, result.begin() + offset);
			offset += data.size();
			if (offset >= result.size())
				break;
		}
		return result;

	}

	void PipePacketer::Read(ByteArray &data, ByteArray &response, int timeout)
	{
		_pipe->ReadInterrupt();
		data.clear();
		response.clear();
		ByteArray message = ReadMessage(timeout);
		//HexDump("message", message);
		InputStream stream(message);
		u16 raw_code;
		stream >> raw_code;
		ContainerType type = ContainerType(raw_code);
		if (type == ContainerType::Data)
		{
			data = std::move(message);
			response = ReadMessage(timeout);
		}
		else
		{
			response = std::move(message);
		}

		//HexDump("response", response);
	}

	DevicePtr Device::Find()
	{
		using namespace mtp;
		usb::ContextPtr ctx(new usb::Context);

		for (usb::DeviceDescriptorPtr desc : ctx->GetDevices())
		{
			usb::DevicePtr device = desc->TryOpen(ctx);
			if (!device)
				continue;
			int confs = desc->GetConfigurationsCount();
			printf("configurations: %d\n", confs);

			for(int i = 0; i < confs; ++i)
			{
				usb::ConfigurationPtr conf = desc->GetConfiguration(i);
				int interfaces = conf->GetInterfaceCount();
				printf("interfaces: %d\n", interfaces);
				for(int j = 0; j < interfaces; ++j)
				{
					usb::InterfacePtr iface = conf->GetInterface(conf, j, 0);
					printf("%d:%d index %u, eps %u\n", i, j, iface->GetIndex(), iface->GetEndpointsCount());
					int name_idx = iface->GetNameIndex();
					if (!name_idx)
						continue;
					std::string name = device->GetString(name_idx);
					if (name == "MTP")
					{
						//device->SetConfiguration(configuration->GetIndex());
						usb::BulkPipePtr pipe = usb::BulkPipe::Create(device, iface);
						return std::make_shared<Device>(pipe);
						break;
					}
				}
			}
		}

		return nullptr;
	}

}
<commit_msg>removed superfluos break<commit_after>#include <mtp/ptp/Device.h>
#include <mtp/ptp/Response.h>
#include <mtp/ptp/Container.h>
#include <mtp/ptp/Messages.h>
#include <mtp/usb/Context.h>
#include <mtp/ptp/OperationRequest.h>

namespace mtp
{

	msg::DeviceInfo Device::GetDeviceInfo()
	{
		OperationRequest req(OperationCode::GetDeviceInfo, 0);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(data, response);
		//HexDump("payload", data);

		InputStream stream(data, 8); //operation code + session id
		msg::DeviceInfo gdi;
		gdi.Read(stream);
		return gdi;
	}

	SessionPtr Device::OpenSession(u32 sessionId)
	{
		OperationRequest req(OperationCode::OpenSession, 0, sessionId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(data, response);
		//HexDump("payload", data);

		return std::make_shared<Session>(_packeter.GetPipe(), sessionId);
	}

	void PipePacketer::Write(const ByteArray &data, int timeout)
	{
		//HexDump("send", data);
		_pipe->Write(data, timeout);
	}

	ByteArray PipePacketer::ReadMessage(int timeout)
	{
		ByteArray result;
		u32 size = ~0u;
		size_t offset = 0;
		size_t packet_offset;
		while(true)
		{
			ByteArray data = _pipe->Read(timeout);
			if (size == ~0u)
			{
				InputStream stream(data);
				stream >> size;
				printf("DATA SIZE = %u\n", size);
				if (size < 4)
					throw std::runtime_error("invalid size");
				packet_offset = 4;
				result.resize(size - 4);
			}
			else
				packet_offset = 0;
			//HexDump("recv", data);

			size_t src_n = std::min(data.size() - packet_offset, result.size() - offset);
			std::copy(data.begin() + packet_offset, data.begin() + packet_offset + src_n, result.begin() + offset);
			offset += data.size();
			if (offset >= result.size())
				break;
		}
		return result;

	}

	void PipePacketer::Read(ByteArray &data, ByteArray &response, int timeout)
	{
		_pipe->ReadInterrupt();
		data.clear();
		response.clear();
		ByteArray message = ReadMessage(timeout);
		//HexDump("message", message);
		InputStream stream(message);
		u16 raw_code;
		stream >> raw_code;
		ContainerType type = ContainerType(raw_code);
		if (type == ContainerType::Data)
		{
			data = std::move(message);
			response = ReadMessage(timeout);
		}
		else
		{
			response = std::move(message);
		}

		//HexDump("response", response);
	}

	DevicePtr Device::Find()
	{
		using namespace mtp;
		usb::ContextPtr ctx(new usb::Context);

		for (usb::DeviceDescriptorPtr desc : ctx->GetDevices())
		{
			usb::DevicePtr device = desc->TryOpen(ctx);
			if (!device)
				continue;
			int confs = desc->GetConfigurationsCount();
			printf("configurations: %d\n", confs);

			for(int i = 0; i < confs; ++i)
			{
				usb::ConfigurationPtr conf = desc->GetConfiguration(i);
				int interfaces = conf->GetInterfaceCount();
				printf("interfaces: %d\n", interfaces);
				for(int j = 0; j < interfaces; ++j)
				{
					usb::InterfacePtr iface = conf->GetInterface(conf, j, 0);
					printf("%d:%d index %u, eps %u\n", i, j, iface->GetIndex(), iface->GetEndpointsCount());
					int name_idx = iface->GetNameIndex();
					if (!name_idx)
						continue;
					std::string name = device->GetString(name_idx);
					if (name == "MTP")
					{
						//device->SetConfiguration(configuration->GetIndex());
						usb::BulkPipePtr pipe = usb::BulkPipe::Create(device, iface);
						return std::make_shared<Device>(pipe);
					}
				}
			}
		}

		return nullptr;
	}

}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/ui/file_picker.h"

#include "xenia/base/assert.h"
#include "xenia/base/platform_win.h"

namespace xe {
namespace ui {

class Win32FilePicker : public FilePicker {
 public:
  Win32FilePicker();
  ~Win32FilePicker() override;

  bool Show(void* parent_window_handle) override;

 private:
};

std::unique_ptr<FilePicker> FilePicker::Create() {
  return std::make_unique<Win32FilePicker>();
}

class CDialogEventHandler : public IFileDialogEvents,
                            public IFileDialogControlEvents {
 public:
  // IUnknown methods
  IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) {
    static const QITAB qit[] = {
        {&__uuidof(IFileDialogEvents),
         OFFSETOFCLASS(IFileDialogEvents, CDialogEventHandler)},
        {&__uuidof(IFileDialogControlEvents),
         OFFSETOFCLASS(IFileDialogControlEvents, CDialogEventHandler)},
        {0},
    };
    return QISearch(this, qit, riid, ppv);
  }

  IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); }

  IFACEMETHODIMP_(ULONG) Release() {
    long cRef = InterlockedDecrement(&_cRef);
    if (!cRef) delete this;
    return cRef;
  }

  // IFileDialogEvents methods
  IFACEMETHODIMP OnFileOk(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnFolderChange(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnFolderChanging(IFileDialog*, IShellItem*) { return S_OK; }
  IFACEMETHODIMP OnHelp(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnSelectionChange(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnShareViolation(IFileDialog*, IShellItem*,
                                  FDE_SHAREVIOLATION_RESPONSE*) {
    return S_OK;
  }
  IFACEMETHODIMP OnTypeChange(IFileDialog* pfd) { return S_OK; }
  IFACEMETHODIMP OnOverwrite(IFileDialog*, IShellItem*,
                             FDE_OVERWRITE_RESPONSE*) {
    return S_OK;
  }

  // IFileDialogControlEvents methods
  IFACEMETHODIMP OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl,
                                DWORD dwIDItem) {
    return S_OK;
  }
  IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize*, DWORD) { return S_OK; }
  IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize*, DWORD, BOOL) {
    return S_OK;
  }
  IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*, DWORD) {
    return S_OK;
  }

  CDialogEventHandler() : _cRef(1) {}

 private:
  virtual ~CDialogEventHandler() = default;
  long _cRef;
};

HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv) {
  *ppv = NULL;
  auto dialog_event_handler = new (std::nothrow) CDialogEventHandler();
  HRESULT hr = dialog_event_handler ? S_OK : E_OUTOFMEMORY;
  if (SUCCEEDED(hr)) {
    hr = dialog_event_handler->QueryInterface(riid, ppv);
    dialog_event_handler->Release();
  }
  return hr;
}

Win32FilePicker::Win32FilePicker() = default;

Win32FilePicker::~Win32FilePicker() = default;

template <typename T>
struct com_ptr {
  com_ptr() : value(nullptr) {}
  ~com_ptr() { reset(); }
  void reset() {
    if (value) {
      value->Release();
      value = nullptr;
    }
  }
  operator T*() { return value; }
  T* operator->() const { return value; }
  T** addressof() { return &value; }
  T* value;
};

bool Win32FilePicker::Show(void* parent_window_handle) {
  // TODO(benvanik): FileSaveDialog.
  assert_true(mode() == Mode::kOpen);
  // TODO(benvanik): folder dialogs.
  assert_true(type() == Type::kFile);

  com_ptr<IFileDialog> file_dialog;
  HRESULT hr =
      CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
                       IID_PPV_ARGS(file_dialog.addressof()));
  if (!SUCCEEDED(hr)) {
    return false;
  }

  hr = file_dialog->SetTitle(title().c_str());
  if (!SUCCEEDED(hr)) {
    return false;
  }

  DWORD flags;
  hr = file_dialog->GetOptions(&flags);
  if (!SUCCEEDED(hr)) {
    return false;
  }
  // FOS_PICKFOLDERS
  // FOS_FILEMUSTEXIST
  // FOS_PATHMUSTEXIST
  flags |= FOS_FORCEFILESYSTEM;
  if (multi_selection()) {
    flags |= FOS_ALLOWMULTISELECT;
  }
  hr = file_dialog->SetOptions(flags);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Set the file types to display only. Notice that this is a 1-based array.
  std::vector<COMDLG_FILTERSPEC> save_types;
  auto extensions = this->extensions();
  for (auto& extension : extensions) {
    save_types.push_back({extension.first.c_str(), extension.second.c_str()});
  }
  hr = file_dialog->SetFileTypes(static_cast<UINT>(save_types.size()),
                                 save_types.data());
  if (!SUCCEEDED(hr)) {
    return false;
  }

  hr = file_dialog->SetFileTypeIndex(1);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Create an event handling object, and hook it up to the dialog.
  com_ptr<IFileDialogEvents> file_dialog_events;
  hr = CDialogEventHandler_CreateInstance(
      IID_PPV_ARGS(file_dialog_events.addressof()));
  if (!SUCCEEDED(hr)) {
    return false;
  }
  DWORD cookie;
  hr = file_dialog->Advise(file_dialog_events, &cookie);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Show the dialog modally.
  hr = file_dialog->Show(static_cast<HWND>(parent_window_handle));
  file_dialog->Unadvise(cookie);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Obtain the result once the user clicks the 'Open' button.
  // The result is an IShellItem object.
  com_ptr<IShellItem> shell_item;
  hr = file_dialog->GetResult(shell_item.addressof());
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // We are just going to print out the name of the file for sample sake.
  PWSTR file_path = nullptr;
  hr = shell_item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
  if (!SUCCEEDED(hr)) {
    return false;
  }
  std::vector<std::wstring> selected_files;
  selected_files.push_back(std::wstring(file_path));
  set_selected_files(selected_files);
  CoTaskMemFree(file_path);

  return true;
}

}  // namespace ui
}  // namespace xe
<commit_msg>[UI] Undo warning fix in file_picker_win.cc<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/ui/file_picker.h"

#include "xenia/base/assert.h"
#include "xenia/base/platform_win.h"

namespace xe {
namespace ui {

class Win32FilePicker : public FilePicker {
 public:
  Win32FilePicker();
  ~Win32FilePicker() override;

  bool Show(void* parent_window_handle) override;

 private:
};

std::unique_ptr<FilePicker> FilePicker::Create() {
  return std::make_unique<Win32FilePicker>();
}

class CDialogEventHandler : public IFileDialogEvents,
                            public IFileDialogControlEvents {
 public:
  // IUnknown methods
  IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) {
    static const QITAB qit[] = {
        {&__uuidof(IFileDialogEvents),
         (int)OFFSETOFCLASS(IFileDialogEvents, CDialogEventHandler)},
        {&__uuidof(IFileDialogControlEvents),
         (int)OFFSETOFCLASS(IFileDialogControlEvents, CDialogEventHandler)},
        {0},
    };
    return QISearch(this, qit, riid, ppv);
  }

  IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); }

  IFACEMETHODIMP_(ULONG) Release() {
    long cRef = InterlockedDecrement(&_cRef);
    if (!cRef) delete this;
    return cRef;
  }

  // IFileDialogEvents methods
  IFACEMETHODIMP OnFileOk(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnFolderChange(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnFolderChanging(IFileDialog*, IShellItem*) { return S_OK; }
  IFACEMETHODIMP OnHelp(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnSelectionChange(IFileDialog*) { return S_OK; }
  IFACEMETHODIMP OnShareViolation(IFileDialog*, IShellItem*,
                                  FDE_SHAREVIOLATION_RESPONSE*) {
    return S_OK;
  }
  IFACEMETHODIMP OnTypeChange(IFileDialog* pfd) { return S_OK; }
  IFACEMETHODIMP OnOverwrite(IFileDialog*, IShellItem*,
                             FDE_OVERWRITE_RESPONSE*) {
    return S_OK;
  }

  // IFileDialogControlEvents methods
  IFACEMETHODIMP OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl,
                                DWORD dwIDItem) {
    return S_OK;
  }
  IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize*, DWORD) { return S_OK; }
  IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize*, DWORD, BOOL) {
    return S_OK;
  }
  IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*, DWORD) {
    return S_OK;
  }

  CDialogEventHandler() : _cRef(1) {}

 private:
  virtual ~CDialogEventHandler() = default;
  long _cRef;
};

HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv) {
  *ppv = NULL;
  auto dialog_event_handler = new (std::nothrow) CDialogEventHandler();
  HRESULT hr = dialog_event_handler ? S_OK : E_OUTOFMEMORY;
  if (SUCCEEDED(hr)) {
    hr = dialog_event_handler->QueryInterface(riid, ppv);
    dialog_event_handler->Release();
  }
  return hr;
}

Win32FilePicker::Win32FilePicker() = default;

Win32FilePicker::~Win32FilePicker() = default;

template <typename T>
struct com_ptr {
  com_ptr() : value(nullptr) {}
  ~com_ptr() { reset(); }
  void reset() {
    if (value) {
      value->Release();
      value = nullptr;
    }
  }
  operator T*() { return value; }
  T* operator->() const { return value; }
  T** addressof() { return &value; }
  T* value;
};

bool Win32FilePicker::Show(void* parent_window_handle) {
  // TODO(benvanik): FileSaveDialog.
  assert_true(mode() == Mode::kOpen);
  // TODO(benvanik): folder dialogs.
  assert_true(type() == Type::kFile);

  com_ptr<IFileDialog> file_dialog;
  HRESULT hr =
      CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
                       IID_PPV_ARGS(file_dialog.addressof()));
  if (!SUCCEEDED(hr)) {
    return false;
  }

  hr = file_dialog->SetTitle(title().c_str());
  if (!SUCCEEDED(hr)) {
    return false;
  }

  DWORD flags;
  hr = file_dialog->GetOptions(&flags);
  if (!SUCCEEDED(hr)) {
    return false;
  }
  // FOS_PICKFOLDERS
  // FOS_FILEMUSTEXIST
  // FOS_PATHMUSTEXIST
  flags |= FOS_FORCEFILESYSTEM;
  if (multi_selection()) {
    flags |= FOS_ALLOWMULTISELECT;
  }
  hr = file_dialog->SetOptions(flags);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Set the file types to display only. Notice that this is a 1-based array.
  std::vector<COMDLG_FILTERSPEC> save_types;
  auto extensions = this->extensions();
  for (auto& extension : extensions) {
    save_types.push_back({extension.first.c_str(), extension.second.c_str()});
  }
  hr = file_dialog->SetFileTypes(static_cast<UINT>(save_types.size()),
                                 save_types.data());
  if (!SUCCEEDED(hr)) {
    return false;
  }

  hr = file_dialog->SetFileTypeIndex(1);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Create an event handling object, and hook it up to the dialog.
  com_ptr<IFileDialogEvents> file_dialog_events;
  hr = CDialogEventHandler_CreateInstance(
      IID_PPV_ARGS(file_dialog_events.addressof()));
  if (!SUCCEEDED(hr)) {
    return false;
  }
  DWORD cookie;
  hr = file_dialog->Advise(file_dialog_events, &cookie);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Show the dialog modally.
  hr = file_dialog->Show(static_cast<HWND>(parent_window_handle));
  file_dialog->Unadvise(cookie);
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // Obtain the result once the user clicks the 'Open' button.
  // The result is an IShellItem object.
  com_ptr<IShellItem> shell_item;
  hr = file_dialog->GetResult(shell_item.addressof());
  if (!SUCCEEDED(hr)) {
    return false;
  }

  // We are just going to print out the name of the file for sample sake.
  PWSTR file_path = nullptr;
  hr = shell_item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
  if (!SUCCEEDED(hr)) {
    return false;
  }
  std::vector<std::wstring> selected_files;
  selected_files.push_back(std::wstring(file_path));
  set_selected_files(selected_files);
  CoTaskMemFree(file_path);

  return true;
}

}  // namespace ui
}  // namespace xe
<|endoftext|>


<commit_before>//
// Created by dar on 11/27/15.
//

#include <stdio.h>
#include <stdlib.h>
#include <gui/GuiText.h>
#include <gui/GuiButton.h>
#include "Game.h"
#include "../core/Core.h"
#include "../core/map/TiledTxtMapLoader.h"
#include "render/RenderManager.h"
#include "InputManager.h"
#include <core/map/entity/EntityBullet.h>
#include <gui/GuiTextBubble.h>
#include <core/map/entity/EntityDoor.h>
#include <core/map/entity/EntityFurniture.h>
#include "../logging.h"

Game::Game(ApplicationContext *applicationContext) : Window(applicationContext) {
    initShapeDefinitions();
    MapLoader *mapLoader = new TiledTxtMapLoader("test_map");
    Map *bmap = mapLoader->loadMap();
    this->core = new Core(bmap);
    delete mapLoader;

    double ringScale = 2 * this->core->getBlockSize();
    this->entityRotationRing = new GuiElement(GUI_TOP_LEFT, 0, 0, ringScale, ringScale, 6);
    this->entityRotationRing->setVisible(false);
    this->entityRotationRing->setAngle(2);
    this->guiElements.push_back(this->entityRotationRing);

    GuiText *t = new GuiText(string("Dev Build: ") + __DATE__ + " " + __TIME__, 15, 15, GUI_BOTTOM_LEFT, 32, 0xFFFFFFFF, 0);
    this->guiElements.push_back(t);
}

void Game::reload(unsigned int windowWidth, unsigned int windowHeight) {
    for (GuiElement *e : this->guiElements) {
        e->reinit(windowWidth, windowHeight);
    }

    this->windowWidth = windowWidth;
    this->windowHeight = windowHeight;
    SDL_StartTextInput();
}

void Game::tick(double deltaTime) {
    this->core->getMap()->update(deltaTime);
    this->core->getMap()->getWorld()->Step(deltaTime, 8, 3);
    for (int i = 0; i < this->core->getMap()->getEntities().size(); i++) {
        Entity *entity = this->core->getMap()->getEntities().at(i);
        if (entity->isToBeDeleted()) {
            this->core->getMap()->removeEntity(entity);
            i--;
        }
    }

    this->core->setCamX(this->core->getPlayer()->getX() + this->core->getPlayer()->getWidth() / 2 - 1);
    this->core->setCamY(this->core->getPlayer()->getY() + this->core->getPlayer()->getHeight() / 2 - 1);
}

void Game::handleKeyboard(const Keypress *const keypress) {
    if (keypress[SDLK_c].isPressed()) {
        double angle = atan2(0, 0) + M_PI; //TODO
        EntityBullet *p = new EntityBullet(this->core->getMap(), angle, 1);
        p->setX(this->core->getPlayer()->getX() - (p->getWidth()) + 0.5 * cos(angle));
        p->setY(this->core->getPlayer()->getY() - (p->getHeight()) + 0.5 * sin(angle));
        this->core->getMap()->addEntity(p);
    }
    if (keypress[SDLK_n].isPressed()) {
        Entity *p;
        switch (rand() % 6) {
            case 0:
                p = new EntityFridge(this->core->getMap());
                break;
            case 1:
                p = new EntityTruck(this->core->getMap());
                break;
            case 2:
                p = new EntityBulldozer(this->core->getMap());
                break;
            case 3:
                p = new EntityWardrobe(this->core->getMap());
                break;
            case 4:
                p = new EntityTable(this->core->getMap());
                break;
            case 5:
                p = new EntityChair(this->core->getMap());
                break;
            default:
                p = new EntityDoor(this->core->getMap(), 0);
                break;
        }
        p->setX(this->core->getPlayer()->getX() - this->core->getPlayer()->getWidth() / 2);
        p->setY(this->core->getPlayer()->getY() - this->core->getPlayer()->getHeight() / 2);
        this->core->getMap()->addEntity(p);
    }
    if (keypress[SDLK_m].isPressed()) {
        SimpleShape *p = new SimpleShape(this->core->getMap(), (unsigned int) (rand() % 3));
        p->setX(this->core->getPlayer()->getX() - this->core->getPlayer()->getWidth() / 2);
        p->setY(this->core->getPlayer()->getY() - this->core->getPlayer()->getHeight() / 2);
        this->core->getMap()->addEntity(p);
    }
    if (keypress[SDLK_k].isPressed()) {
        if (this->core->getPlayer()->getToy() == nullptr) {
            this->core->getPlayer()->setToy();
        } else {
            this->core->getPlayer()->eject();
        }
    }
    double playerSpeed = 1.0;
    if (!this->entityRotationRing->isVisible()) {
        if (keypress[SDLK_w].isDown()) {
            this->core->getPlayer()->applyImpulse(0, -playerSpeed);
        }
        if (keypress[SDLK_s].isDown()) {
            this->core->getPlayer()->applyImpulse(0, playerSpeed);
        }
        if (keypress[SDLK_a].isDown()) {
            this->core->getPlayer()->applyImpulse(-playerSpeed, 0);
        }
        if (keypress[SDLK_d].isDown()) {
            this->core->getPlayer()->applyImpulse(playerSpeed, 0);
        }
    }
    if (keypress[SDLK_q].isPressed()) {
        this->core->stop();
    }
    if (keypress[SDLK_p].isPressed()) {
        this->core->getMap()->saveEntities();
    }
    if (keypress[SDLK_MINUS].isDown()) {
        this->core->setBlockSize(this->core->getBlockSize() - 0.15);
    }
    if (keypress[SDLK_EQUALS].isDown()) {
        this->core->setBlockSize(this->core->getBlockSize() + 0.15);
    }
}

void Game::handleClick(const TouchPoint *const p) {
    float x = (float) ((-this->core->getCamX() - ((double) this->windowWidth / (2.0) - p->x) / (this->core->getGeneralScale() * this->core->getBlockSize())) + 0.5);
    float y = (float) ((-this->core->getCamY() - ((double) this->windowHeight / (2.0) - p->y) / (this->core->getGeneralScale() * this->core->getBlockSize())) + 0.5);
    if (p->id == SDL_BUTTON_LEFT) {
        if (p->state == 0) {
            this->heldEntity = this->core->getMap()->getEntityAt<Entity>(x, y);
            this->relXClicked = this->heldEntity->getX() - x;
            this->relYClicked = this->heldEntity->getY() - y;
        } else if (p->state == 2) {
            if (this->heldEntity != nullptr && !this->entityRotationRing->isVisible()) {
                Entity *e = this->heldEntity;
                e->setX(x + relXClicked);
                e->setY(y + relYClicked);
            }
        } else if (p->state == 1) {
            if (this->heldEntity == nullptr) {
                /*SimpleShape *s = new SimpleShape(this->core->getMap(), (unsigned int) (rand() % 3));
                s->setX(x + s->getWidth() / 2);
                s->setY(y + s->getWidth() / 2);
                this->core->getMap()->addEntity(s);*/
            } else {
                this->heldEntity = nullptr;
                if (this->entityRotationRing->isVisible()) {
                    this->entityRotationRing->setVisible(false);
                    SDL_ShowCursor(true);
                    SDL_WarpMouseGlobal(this->mouseLockX, this->mouseLockY);
                }
            }
        }
    } else if (p->id == SDL_BUTTON_MIDDLE) {
        if (p->state == 0) {
            this->heldEntity = this->core->getMap()->getEntityAt<Entity>(x, y);
        } else if (p->state == 1) {
            if (this->heldEntity != nullptr && this->core->getMap()->getEntityAt<Entity>(x, y) == this->heldEntity) {
                this->heldEntity->remove();
            }
        }
    } else if (p->id == SDL_BUTTON_RIGHT) {
        if (p->state == 0) {
            if (this->heldEntity != nullptr) {
                double scale = this->core->getGeneralScale() * this->core->getBlockSize();
                double player_x = this->windowWidth / 2.0 + (this->heldEntity->getBody()->GetPosition().x + this->core->getCamX() - 0.5) * scale;
                double player_y = this->windowHeight / 2.0 + (this->heldEntity->getBody()->GetPosition().y + this->core->getCamY() - 0.5) * scale;
                this->entityRotationRing->setX(player_x - this->entityRotationRing->getWidth() / 2);
                this->entityRotationRing->setY(player_y - this->entityRotationRing->getHeight() / 2);
                this->defaultAngle = this->heldEntity->getAngle();
                this->entityRotationRing->setVisible(true);
                SDL_GetGlobalMouseState(&this->mouseLockX, &this->mouseLockY);
                SDL_ShowCursor(false);
            }
        } else if (p->state == 2) {
            if (this->heldEntity != nullptr) {
                int x, y;
                SDL_GetGlobalMouseState(&x, &y);
                double angle = this->defaultAngle + 10.0 * (x - this->mouseLockX) / this->windowWidth;
                this->entityRotationRing->setAngle(angle);
                this->heldEntity->setAngle(angle);
            }
        } else if (p->state == 1) {
            if (this->entityRotationRing->isVisible()) {
                this->entityRotationRing->setVisible(false);
                SDL_ShowCursor(true);
                SDL_WarpMouseGlobal(this->mouseLockX, this->mouseLockY);
            }
        }
    }
}

Game::~Game() {
    SDL_StopTextInput();
    delete this->core;
}
<commit_msg>Fixed segfault when no entity was selected upon LMB click<commit_after>//
// Created by dar on 11/27/15.
//

#include <stdio.h>
#include <stdlib.h>
#include <gui/GuiText.h>
#include <gui/GuiButton.h>
#include "Game.h"
#include "../core/Core.h"
#include "../core/map/TiledTxtMapLoader.h"
#include "render/RenderManager.h"
#include "InputManager.h"
#include <core/map/entity/EntityBullet.h>
#include <gui/GuiTextBubble.h>
#include <core/map/entity/EntityDoor.h>
#include <core/map/entity/EntityFurniture.h>
#include "../logging.h"

Game::Game(ApplicationContext *applicationContext) : Window(applicationContext) {
    initShapeDefinitions();
    MapLoader *mapLoader = new TiledTxtMapLoader("test_map");
    Map *bmap = mapLoader->loadMap();
    this->core = new Core(bmap);
    delete mapLoader;

    double ringScale = 2 * this->core->getBlockSize();
    this->entityRotationRing = new GuiElement(GUI_TOP_LEFT, 0, 0, ringScale, ringScale, 6);
    this->entityRotationRing->setVisible(false);
    this->entityRotationRing->setAngle(2);
    this->guiElements.push_back(this->entityRotationRing);

    GuiText *t = new GuiText(string("Dev Build: ") + __DATE__ + " " + __TIME__, 15, 15, GUI_BOTTOM_LEFT, 32, 0xFFFFFFFF, 0);
    this->guiElements.push_back(t);
}

void Game::reload(unsigned int windowWidth, unsigned int windowHeight) {
    for (GuiElement *e : this->guiElements) {
        e->reinit(windowWidth, windowHeight);
    }

    this->windowWidth = windowWidth;
    this->windowHeight = windowHeight;
    SDL_StartTextInput();
}

void Game::tick(double deltaTime) {
    this->core->getMap()->update(deltaTime);
    this->core->getMap()->getWorld()->Step(deltaTime, 8, 3);
    for (int i = 0; i < this->core->getMap()->getEntities().size(); i++) {
        Entity *entity = this->core->getMap()->getEntities().at(i);
        if (entity->isToBeDeleted()) {
            this->core->getMap()->removeEntity(entity);
            i--;
        }
    }

    this->core->setCamX(this->core->getPlayer()->getX() + this->core->getPlayer()->getWidth() / 2 - 1);
    this->core->setCamY(this->core->getPlayer()->getY() + this->core->getPlayer()->getHeight() / 2 - 1);
}

void Game::handleKeyboard(const Keypress *const keypress) {
    if (keypress[SDLK_c].isPressed()) {
        double angle = atan2(0, 0) + M_PI; //TODO
        EntityBullet *p = new EntityBullet(this->core->getMap(), angle, 1);
        p->setX(this->core->getPlayer()->getX() - (p->getWidth()) + 0.5 * cos(angle));
        p->setY(this->core->getPlayer()->getY() - (p->getHeight()) + 0.5 * sin(angle));
        this->core->getMap()->addEntity(p);
    }
    if (keypress[SDLK_n].isPressed()) {
        Entity *p;
        switch (rand() % 6) {
            case 0:
                p = new EntityFridge(this->core->getMap());
                break;
            case 1:
                p = new EntityTruck(this->core->getMap());
                break;
            case 2:
                p = new EntityBulldozer(this->core->getMap());
                break;
            case 3:
                p = new EntityWardrobe(this->core->getMap());
                break;
            case 4:
                p = new EntityTable(this->core->getMap());
                break;
            case 5:
                p = new EntityChair(this->core->getMap());
                break;
            default:
                p = new EntityDoor(this->core->getMap(), 0);
                break;
        }
        p->setX(this->core->getPlayer()->getX() - this->core->getPlayer()->getWidth() / 2);
        p->setY(this->core->getPlayer()->getY() - this->core->getPlayer()->getHeight() / 2);
        this->core->getMap()->addEntity(p);
    }
    if (keypress[SDLK_m].isPressed()) {
        SimpleShape *p = new SimpleShape(this->core->getMap(), (unsigned int) (rand() % 3));
        p->setX(this->core->getPlayer()->getX() - this->core->getPlayer()->getWidth() / 2);
        p->setY(this->core->getPlayer()->getY() - this->core->getPlayer()->getHeight() / 2);
        this->core->getMap()->addEntity(p);
    }
    if (keypress[SDLK_k].isPressed()) {
        if (this->core->getPlayer()->getToy() == nullptr) {
            this->core->getPlayer()->setToy();
        } else {
            this->core->getPlayer()->eject();
        }
    }
    double playerSpeed = 1.0;
    if (!this->entityRotationRing->isVisible()) {
        if (keypress[SDLK_w].isDown()) {
            this->core->getPlayer()->applyImpulse(0, -playerSpeed);
        }
        if (keypress[SDLK_s].isDown()) {
            this->core->getPlayer()->applyImpulse(0, playerSpeed);
        }
        if (keypress[SDLK_a].isDown()) {
            this->core->getPlayer()->applyImpulse(-playerSpeed, 0);
        }
        if (keypress[SDLK_d].isDown()) {
            this->core->getPlayer()->applyImpulse(playerSpeed, 0);
        }
    }
    if (keypress[SDLK_q].isPressed()) {
        this->core->stop();
    }
    if (keypress[SDLK_p].isPressed()) {
        this->core->getMap()->saveEntities();
    }
    if (keypress[SDLK_MINUS].isDown()) {
        this->core->setBlockSize(this->core->getBlockSize() - 0.15);
    }
    if (keypress[SDLK_EQUALS].isDown()) {
        this->core->setBlockSize(this->core->getBlockSize() + 0.15);
    }
}

void Game::handleClick(const TouchPoint *const p) {
    float x = (float) ((-this->core->getCamX() - ((double) this->windowWidth / (2.0) - p->x) / (this->core->getGeneralScale() * this->core->getBlockSize())) + 0.5);
    float y = (float) ((-this->core->getCamY() - ((double) this->windowHeight / (2.0) - p->y) / (this->core->getGeneralScale() * this->core->getBlockSize())) + 0.5);
    if (p->id == SDL_BUTTON_LEFT) {
        if (p->state == 0) {
            this->heldEntity = this->core->getMap()->getEntityAt<Entity>(x, y);
            if (this->heldEntity != nullptr) {
                this->relXClicked = this->heldEntity->getX() - x;
                this->relYClicked = this->heldEntity->getY() - y;
            }
        } else if (p->state == 2) {
            if (this->heldEntity != nullptr && !this->entityRotationRing->isVisible()) {
                Entity *e = this->heldEntity;
                e->setX(x + relXClicked);
                e->setY(y + relYClicked);
            }
        } else if (p->state == 1) {
            if (this->heldEntity == nullptr) {
                /*SimpleShape *s = new SimpleShape(this->core->getMap(), (unsigned int) (rand() % 3));
                s->setX(x + s->getWidth() / 2);
                s->setY(y + s->getWidth() / 2);
                this->core->getMap()->addEntity(s);*/
            } else {
                this->heldEntity = nullptr;
                if (this->entityRotationRing->isVisible()) {
                    this->entityRotationRing->setVisible(false);
                    SDL_ShowCursor(true);
                    SDL_WarpMouseGlobal(this->mouseLockX, this->mouseLockY);
                }
            }
        }
    } else if (p->id == SDL_BUTTON_MIDDLE) {
        if (p->state == 0) {
            this->heldEntity = this->core->getMap()->getEntityAt<Entity>(x, y);
        } else if (p->state == 1) {
            if (this->heldEntity != nullptr && this->core->getMap()->getEntityAt<Entity>(x, y) == this->heldEntity) {
                this->heldEntity->remove();
            }
        }
    } else if (p->id == SDL_BUTTON_RIGHT) {
        if (p->state == 0) {
            if (this->heldEntity != nullptr) {
                double scale = this->core->getGeneralScale() * this->core->getBlockSize();
                double player_x = this->windowWidth / 2.0 + (this->heldEntity->getBody()->GetPosition().x + this->core->getCamX() - 0.5) * scale;
                double player_y = this->windowHeight / 2.0 + (this->heldEntity->getBody()->GetPosition().y + this->core->getCamY() - 0.5) * scale;
                this->entityRotationRing->setX(player_x - this->entityRotationRing->getWidth() / 2);
                this->entityRotationRing->setY(player_y - this->entityRotationRing->getHeight() / 2);
                this->defaultAngle = this->heldEntity->getAngle();
                this->entityRotationRing->setVisible(true);
                SDL_GetGlobalMouseState(&this->mouseLockX, &this->mouseLockY);
                SDL_ShowCursor(false);
            }
        } else if (p->state == 2) {
            if (this->heldEntity != nullptr) {
                int x, y;
                SDL_GetGlobalMouseState(&x, &y);
                double angle = this->defaultAngle + 10.0 * (x - this->mouseLockX) / this->windowWidth;
                this->entityRotationRing->setAngle(angle);
                this->heldEntity->setAngle(angle);
            }
        } else if (p->state == 1) {
            if (this->entityRotationRing->isVisible()) {
                this->entityRotationRing->setVisible(false);
                SDL_ShowCursor(true);
                SDL_WarpMouseGlobal(this->mouseLockX, this->mouseLockY);
            }
        }
    }
}

Game::~Game() {
    SDL_StopTextInput();
    delete this->core;
}
<|endoftext|>


<commit_before>//
//  Keyboard.h
//  Clock Signal
//
//  Created by Thomas Harte on 08/05/2019.
//  Copyright © 2019 Thomas Harte. All rights reserved.
//

#ifndef Apple_Macintosh_Keyboard_hpp
#define Apple_Macintosh_Keyboard_hpp

#include "../../KeyboardMachine.hpp"

#include <mutex>
#include <vector>

namespace Apple {
namespace Macintosh {

class Keyboard {
	public:
		void set_input(bool data) {
			switch(mode_) {
				case Mode::Waiting:
					/*
						"Only the computer can initiate communication over the keyboard lines. When the computer and keyboard
						are turned on, the computer is in charge of the keyboard interface and the keyboard is passive. The
						computer signals that it is ready to begin communication by pulling the Keyboard Data line low."
					*/
					if(!data) {
						mode_ = Mode::AcceptingCommand;
						phase_ = 0;
						command_ = 0;
					}
				break;

				case Mode::AcceptingCommand:
					/* Note value, so that it can be latched upon a clock transition. */
					data_input_ = data;
				break;

				case Mode::AwaitingEndOfCommand:
					/*
						The last bit of the command leaves the Keyboard Data line low; the computer then indicates that it is ready
						to receive the keyboard's response by setting the Keyboard Data line high.
					*/
					if(data) {
						mode_ = Mode::PerformingCommand;
						phase_ = 0;
					}
				break;

				default:
				case Mode::SendingResponse:
					/* This line isn't currently an input; do nothing. */
				break;
			}
		}

		bool get_clock() {
			return clock_output_;
		}

		bool get_data() {
			return !!(response_ & 0x80);
		}

		/*!
			The keyboard expects ~10 µs-frequency ticks, i.e. a clock rate of just around 100 kHz.
		*/
		void run_for(HalfCycles cycle) {
			switch(mode_) {
				default:
				case Mode::Waiting: return;

				case Mode::AcceptingCommand: {
					/*
						"When the computer is sending data to the keyboard, the keyboard transmits eight cycles of 400 µS each (180 µS low,
						220 µS high) on the Keyboard Clock line. On the falling edge of each keyboard clock cycle, the Macintosh Plus places
						a data bit on the data line and holds it there for 400 µS. The keyboard reads the data bit 80 µS after the rising edge
						of the Keyboard Clock signal."
					*/
					const auto offset = phase_ % 40;
					clock_output_ = offset >= 18;

					if(offset == 26) {
						command_ = (command_ << 1) | (data_input_ ? 1 : 0);
					}

					++phase_;
					if(phase_ == 8*40) {
						mode_ = Mode::AwaitingEndOfCommand;
						phase_ = 0;
						clock_output_ = false;
					}
				} break;

				case Mode::AwaitingEndOfCommand:
					// Time out if the end-of-command seems not to be forthcoming.
					// This is an elaboration on my part; a guess.
					++phase_;
					if(phase_ == 1000) {
						clock_output_ = false;
						mode_ = Mode::Waiting;
						phase_ = 0;
					}
				return;

				case Mode::PerformingCommand: {
					response_ = perform_command(command_);

					// Inquiry has a 0.25-second timeout; everything else is instant.
					++phase_;
					if(phase_ == 25000 || command_ != 0x10 || response_ != 0x7b) {
						mode_ = Mode::SendingResponse;
						phase_ = 0;
					}
				} break;

				case Mode::SendingResponse: {
					/*
						"When sending data to the computer, the keyboard transmits eight cycles of 330 µS each (160 µS low, 170 µS high)
						on the normally high Keyboard Clock line. It places a data bit on the data line 40 µS before the falling edge of each
						clock cycle and maintains it for 330 µS. The VIA in the computer latches the data bit into its shift register on the
						rising edge of the Keyboard Clock signal."
					*/
					const auto offset = phase_ % 33;
					clock_output_ = offset >= 16;

					if(offset == 29) {
						response_ <<= 1;
					}

					++phase_;
					if(phase_ == 8*33) {
						clock_output_ = false;
						mode_ = Mode::Waiting;
						phase_ = 0;
					}
				} break;
			}
		}

		void enqueue_key_state(uint16_t key, bool is_pressed) {
			// Front insert; messages will be pop_back'd.
			std::lock_guard<decltype(key_queue_mutex_)> lock(key_queue_mutex_);
			key_queue_.insert(key_queue_.begin(), (is_pressed ? 0x00 : 0x80) | uint8_t(key));
		}

	private:

		int perform_command(int command) {
			switch(command) {
				case 0x10:		// Inquiry.
				case 0x14: {	// Instant.
					std::lock_guard<decltype(key_queue_mutex_)> lock(key_queue_mutex_);
					if(!key_queue_.empty()) {
						const auto new_message = key_queue_.back();
						key_queue_.pop_back();
						return new_message;
					}
				} break;

				case 0x16:	// Model number.
				return
					0x01 |			// b0: always 1
					(1 << 1) |		// keyboard model number
					(1 << 4);		// next device number
									// (b7 not set => no next device)

				case 0x36:	// Test
				return 0x7d;		// 0x7d = ACK, 0x77 = not ACK.
			}
			return 0x7b;	// No key transition.
		}

		enum class Mode {
			Waiting,
			AcceptingCommand,
			AwaitingEndOfCommand,
			SendingResponse,
			PerformingCommand
		} mode_ = Mode::Waiting;
		int phase_ = 0;
		int command_ = 0;
		int response_ = 0;

		bool data_input_ = false;
		bool clock_output_ = false;

		// TODO: improve this very, very simple implementation.
		std::mutex key_queue_mutex_;
		std::vector<uint8_t> key_queue_;
};

/*!
	Provides a mapping from idiomatic PC keys to Macintosh keys.
*/
class KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
	uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) override {
		using Key = Inputs::Keyboard::Key;
		switch(key) {
			default: return KeyboardMachine::MappedMachine::KeyNotMapped;

			/*
				See p284 of the Apple Guide to the Macintosh Family Hardware
				for documentation of the mapping below.
			*/

			case Key::BackTick:				return 0x65;
			case Key::k1:					return 0x25;
			case Key::k2:					return 0x27;
			case Key::k3:					return 0x29;
			case Key::k4:					return 0x2b;
			case Key::k5:					return 0x2f;
			case Key::k6:					return 0x2d;
			case Key::k7:					return 0x35;
			case Key::k8:					return 0x39;
			case Key::k9:					return 0x33;
			case Key::k0:					return 0x3b;
			case Key::Hyphen:				return 0x37;
			case Key::Equals:				return 0x31;
			case Key::BackSpace:			return 0x67;

			case Key::Tab:					return 0x61;
			case Key::Q:					return 0x19;
			case Key::W:					return 0x1b;
			case Key::E:					return 0x1d;
			case Key::R:					return 0x1f;
			case Key::T:					return 0x23;
			case Key::Y:					return 0x21;
			case Key::U:					return 0x41;
			case Key::I:					return 0x45;
			case Key::O:					return 0x3f;
			case Key::P:					return 0x47;
			case Key::OpenSquareBracket:	return 0x43;
			case Key::CloseSquareBracket:	return 0x3d;

			case Key::CapsLock:				return 0x73;
			case Key::A:					return 0x01;
			case Key::S:					return 0x03;
			case Key::D:					return 0x05;
			case Key::F:					return 0x07;
			case Key::G:					return 0x0b;
			case Key::H:					return 0x09;
			case Key::J:					return 0x4d;
			case Key::K:					return 0x51;
			case Key::L:					return 0x4b;
			case Key::Semicolon:			return 0x53;
			case Key::Quote:				return 0x4f;
			case Key::Enter:				return 0x49;

			case Key::LeftShift:			return 0x71;
			case Key::Z:					return 0x0d;
			case Key::X:					return 0x0f;
			case Key::C:					return 0x11;
			case Key::V:					return 0x13;
			case Key::B:					return 0x17;
			case Key::N:					return 0x5b;
			case Key::M:					return 0x5d;
			case Key::Comma:				return 0x57;
			case Key::FullStop:				return 0x5f;
			case Key::ForwardSlash:			return 0x59;
			case Key::RightShift:			return 0x71;

			case Key::Left:					return 0x0d;
			case Key::Right:				return 0x05;
			case Key::Up:					return 0x1b;
			case Key::Down:					return 0x11;

			case Key::LeftOption:
			case Key::RightOption:			return 0x75;
			case Key::LeftMeta:
			case Key::RightMeta:			return 0x6f;

			case Key::Space:				return 0x63;
			case Key::BackSlash:			return 0x55;

			/* TODO: the numeric keypad. */
		}
	}

};

}
}

#endif /* Apple_Macintosh_Keyboard_hpp */
<commit_msg>Fixes keypad keys.<commit_after>//
//  Keyboard.h
//  Clock Signal
//
//  Created by Thomas Harte on 08/05/2019.
//  Copyright © 2019 Thomas Harte. All rights reserved.
//

#ifndef Apple_Macintosh_Keyboard_hpp
#define Apple_Macintosh_Keyboard_hpp

#include "../../KeyboardMachine.hpp"

#include <mutex>
#include <vector>

namespace Apple {
namespace Macintosh {

class Keyboard {
	public:
		void set_input(bool data) {
			switch(mode_) {
				case Mode::Waiting:
					/*
						"Only the computer can initiate communication over the keyboard lines. When the computer and keyboard
						are turned on, the computer is in charge of the keyboard interface and the keyboard is passive. The
						computer signals that it is ready to begin communication by pulling the Keyboard Data line low."
					*/
					if(!data) {
						mode_ = Mode::AcceptingCommand;
						phase_ = 0;
						command_ = 0;
					}
				break;

				case Mode::AcceptingCommand:
					/* Note value, so that it can be latched upon a clock transition. */
					data_input_ = data;
				break;

				case Mode::AwaitingEndOfCommand:
					/*
						The last bit of the command leaves the Keyboard Data line low; the computer then indicates that it is ready
						to receive the keyboard's response by setting the Keyboard Data line high.
					*/
					if(data) {
						mode_ = Mode::PerformingCommand;
						phase_ = 0;
					}
				break;

				default:
				case Mode::SendingResponse:
					/* This line isn't currently an input; do nothing. */
				break;
			}
		}

		bool get_clock() {
			return clock_output_;
		}

		bool get_data() {
			return !!(response_ & 0x80);
		}

		/*!
			The keyboard expects ~10 µs-frequency ticks, i.e. a clock rate of just around 100 kHz.
		*/
		void run_for(HalfCycles cycle) {
			switch(mode_) {
				default:
				case Mode::Waiting: return;

				case Mode::AcceptingCommand: {
					/*
						"When the computer is sending data to the keyboard, the keyboard transmits eight cycles of 400 µS each (180 µS low,
						220 µS high) on the Keyboard Clock line. On the falling edge of each keyboard clock cycle, the Macintosh Plus places
						a data bit on the data line and holds it there for 400 µS. The keyboard reads the data bit 80 µS after the rising edge
						of the Keyboard Clock signal."
					*/
					const auto offset = phase_ % 40;
					clock_output_ = offset >= 18;

					if(offset == 26) {
						command_ = (command_ << 1) | (data_input_ ? 1 : 0);
					}

					++phase_;
					if(phase_ == 8*40) {
						mode_ = Mode::AwaitingEndOfCommand;
						phase_ = 0;
						clock_output_ = false;
					}
				} break;

				case Mode::AwaitingEndOfCommand:
					// Time out if the end-of-command seems not to be forthcoming.
					// This is an elaboration on my part; a guess.
					++phase_;
					if(phase_ == 1000) {
						clock_output_ = false;
						mode_ = Mode::Waiting;
						phase_ = 0;
					}
				return;

				case Mode::PerformingCommand: {
					response_ = perform_command(command_);

					// Inquiry has a 0.25-second timeout; everything else is instant.
					++phase_;
					if(phase_ == 25000 || command_ != 0x10 || response_ != 0x7b) {
						mode_ = Mode::SendingResponse;
						phase_ = 0;
					}
				} break;

				case Mode::SendingResponse: {
					/*
						"When sending data to the computer, the keyboard transmits eight cycles of 330 µS each (160 µS low, 170 µS high)
						on the normally high Keyboard Clock line. It places a data bit on the data line 40 µS before the falling edge of each
						clock cycle and maintains it for 330 µS. The VIA in the computer latches the data bit into its shift register on the
						rising edge of the Keyboard Clock signal."
					*/
					const auto offset = phase_ % 33;
					clock_output_ = offset >= 16;

					if(offset == 29) {
						response_ <<= 1;
					}

					++phase_;
					if(phase_ == 8*33) {
						clock_output_ = false;
						mode_ = Mode::Waiting;
						phase_ = 0;
					}
				} break;
			}
		}

		void enqueue_key_state(uint16_t key, bool is_pressed) {
			// Front insert; messages will be pop_back'd.
			std::lock_guard<decltype(key_queue_mutex_)> lock(key_queue_mutex_);

			// Keys on the keypad are preceded by a $79 keycode; in the internal naming scheme
			// they are indicated by having bit 8 set. So add the $79 prefix if required.
			if(key & 0x100) {
				key_queue_.insert(key_queue_.begin(), 0x79);
			}
			key_queue_.insert(key_queue_.begin(), (is_pressed ? 0x00 : 0x80) | uint8_t(key));
		}

	private:

		int perform_command(int command) {
			switch(command) {
				case 0x10:		// Inquiry.
				case 0x14: {	// Instant.
					std::lock_guard<decltype(key_queue_mutex_)> lock(key_queue_mutex_);
					if(!key_queue_.empty()) {
						const auto new_message = key_queue_.back();
						key_queue_.pop_back();
						return new_message;
					}
				} break;

				case 0x16:	// Model number.
				return
					0x01 |			// b0: always 1
					(1 << 1) |		// keyboard model number
					(1 << 4);		// next device number
									// (b7 not set => no next device)

				case 0x36:	// Test
				return 0x7d;		// 0x7d = ACK, 0x77 = not ACK.
			}
			return 0x7b;	// No key transition.
		}

		enum class Mode {
			Waiting,
			AcceptingCommand,
			AwaitingEndOfCommand,
			SendingResponse,
			PerformingCommand
		} mode_ = Mode::Waiting;
		int phase_ = 0;
		int command_ = 0;
		int response_ = 0;

		bool data_input_ = false;
		bool clock_output_ = false;

		// TODO: improve this very, very simple implementation.
		std::mutex key_queue_mutex_;
		std::vector<uint8_t> key_queue_;
};

/*!
	Provides a mapping from idiomatic PC keys to Macintosh keys.
*/
class KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
	uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) override {
		using Key = Inputs::Keyboard::Key;
		switch(key) {
			default: return KeyboardMachine::MappedMachine::KeyNotMapped;

			/*
				See p284 of the Apple Guide to the Macintosh Family Hardware
				for documentation of the mapping below.
			*/

			case Key::BackTick:				return 0x65;
			case Key::k1:					return 0x25;
			case Key::k2:					return 0x27;
			case Key::k3:					return 0x29;
			case Key::k4:					return 0x2b;
			case Key::k5:					return 0x2f;
			case Key::k6:					return 0x2d;
			case Key::k7:					return 0x35;
			case Key::k8:					return 0x39;
			case Key::k9:					return 0x33;
			case Key::k0:					return 0x3b;
			case Key::Hyphen:				return 0x37;
			case Key::Equals:				return 0x31;
			case Key::BackSpace:			return 0x67;

			case Key::Tab:					return 0x61;
			case Key::Q:					return 0x19;
			case Key::W:					return 0x1b;
			case Key::E:					return 0x1d;
			case Key::R:					return 0x1f;
			case Key::T:					return 0x23;
			case Key::Y:					return 0x21;
			case Key::U:					return 0x41;
			case Key::I:					return 0x45;
			case Key::O:					return 0x3f;
			case Key::P:					return 0x47;
			case Key::OpenSquareBracket:	return 0x43;
			case Key::CloseSquareBracket:	return 0x3d;

			case Key::CapsLock:				return 0x73;
			case Key::A:					return 0x01;
			case Key::S:					return 0x03;
			case Key::D:					return 0x05;
			case Key::F:					return 0x07;
			case Key::G:					return 0x0b;
			case Key::H:					return 0x09;
			case Key::J:					return 0x4d;
			case Key::K:					return 0x51;
			case Key::L:					return 0x4b;
			case Key::Semicolon:			return 0x53;
			case Key::Quote:				return 0x4f;
			case Key::Enter:				return 0x49;

			case Key::LeftShift:			return 0x71;
			case Key::Z:					return 0x0d;
			case Key::X:					return 0x0f;
			case Key::C:					return 0x11;
			case Key::V:					return 0x13;
			case Key::B:					return 0x17;
			case Key::N:					return 0x5b;
			case Key::M:					return 0x5d;
			case Key::Comma:				return 0x57;
			case Key::FullStop:				return 0x5f;
			case Key::ForwardSlash:			return 0x59;
			case Key::RightShift:			return 0x71;

			case Key::Left:					return 0x100 | 0x0d;
			case Key::Right:				return 0x100 | 0x05;
			case Key::Up:					return 0x100 | 0x1b;
			case Key::Down:					return 0x100 | 0x11;

			case Key::LeftOption:
			case Key::RightOption:			return 0x75;
			case Key::LeftMeta:
			case Key::RightMeta:			return 0x6f;

			case Key::Space:				return 0x63;
			case Key::BackSlash:			return 0x55;

			/* TODO: the numeric keypad. */
		}
	}

};

}
}

#endif /* Apple_Macintosh_Keyboard_hpp */
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Nico Blodow (blodow@cs.tum.edu)
 */

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/time.h> //fps calculations
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/openni_camera/openni_driver.h>

#define SHOW_FPS 1
#if SHOW_FPS
#define FPS_CALC(_WHAT_) \
do \
{ \
    static unsigned count = 0;\
    static double last = pcl::getTime ();\
    if (++count == 100) \
    { \
      double now = pcl::getTime (); \
      std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" <<  std::endl; \
      count = 0; \
      last = now; \
    } \
}while(false)
#else
#define FPS_CALC(_WHAT_) \
do \
{ \
}while(false)
#endif

template <typename PointType>
class SimpleOpenNIViewer
{
  public:
    typedef pcl::PointCloud<PointType> Cloud;
    typedef typename Cloud::ConstPtr CloudConstPtr;

    SimpleOpenNIViewer (const std::string& device_id = "")
    : viewer ("PCL OpenNI Viewer")
    , device_id_(device_id)
    {}

    void
    cloud_cb_ (const CloudConstPtr& cloud)
    {
      FPS_CALC("callback");
      set(cloud);
    }

    void
    set(const CloudConstPtr& cloud)
    {
      //lock while we set our cloud;
      boost::mutex::scoped_lock lock(mtx_);
      cloud_  = cloud;
    }

    CloudConstPtr
    get(){
      //lock while we swap our cloud and reset it.
      boost::mutex::scoped_lock lock(mtx_);
      CloudConstPtr temp_cloud;
      temp_cloud.swap(cloud_);       //here we set cloud_ to null, so that
                                     //it is safe to set it again from our
                                     //callback
      return temp_cloud;
    }

    void
    run ()
    {
      pcl::Grabber* interface = new pcl::OpenNIGrabber(device_id_);

      boost::function<void (const CloudConstPtr&)> f =
        boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);

      boost::signals2::connection c = interface->registerCallback (f);

      interface->start ();

      while (!viewer.wasStopped ())
      {
        if(cloud_)
        {
          FPS_CALC("drawing");
          //the call to get() sets the cloud_ to null;
          viewer.showCloud ( get() );
        }
      }

      interface->stop ();
    }

    pcl::visualization::CloudViewer viewer;
    std::string device_id_;
    boost::mutex mtx_;
    CloudConstPtr cloud_;
};

void
usage(char ** argv)
{
  std::cout << "usage: " << argv[0] << " <device_id>\n";

  openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance ();
  if (driver.getNumberDevices () > 0)
  {
    for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices (); ++deviceIdx)
    {
      cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName (deviceIdx) << ", product: " << driver.getProductName (deviceIdx)
              << ", connected: " << (int)driver.getBus (deviceIdx) << " @ " << (int)driver.getAddress (deviceIdx) << ", serial number: \'" << driver.getSerialNumber (deviceIdx) << "\'" << endl;
      cout << "device_id may be #1, #2, ... for the first second etc device in the list or" << endl
           << "                 bus@address for the device connected to a specific usb-bus / address combination (wotks only in Linux) or" << endl
           << "                 <serial-number> (only in Linux and for devices which provide serial numbers)"  << endl;
    }
  }
  else
    cout << "No devices connected." << endl;
}

int
main (int argc, char ** argv)
{
  if(argc != 2)
  {
    usage(argv);
    return 1;
  }

  std::string arg(argv[1]);

  if( arg == "--help" || arg == "-h")
  {
    usage(argv);
    return 1;
  }

  pcl::OpenNIGrabber grabber(arg);
  if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb> ())
  {
    SimpleOpenNIViewer<pcl::PointXYZRGB> v(arg);
    v.run ();
  }
  else
  {
    SimpleOpenNIViewer<pcl::PointXYZ> v(arg);
    v.run ();
  }

  return (0);
}
<commit_msg>simple indents<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Nico Blodow (blodow@cs.tum.edu)
 */

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/time.h> //fps calculations
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/openni_camera/openni_driver.h>

#define SHOW_FPS 1
#if SHOW_FPS
#define FPS_CALC(_WHAT_) \
do \
{ \
    static unsigned count = 0;\
    static double last = pcl::getTime ();\
    if (++count == 100) \
    { \
      double now = pcl::getTime (); \
      std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" <<  std::endl; \
      count = 0; \
      last = now; \
    } \
}while(false)
#else
#define FPS_CALC(_WHAT_) \
do \
{ \
}while(false)
#endif

template <typename PointType>
class SimpleOpenNIViewer
{
  public:
    typedef pcl::PointCloud<PointType> Cloud;
    typedef typename Cloud::ConstPtr CloudConstPtr;

    SimpleOpenNIViewer (const std::string& device_id = "")
    : viewer ("PCL OpenNI Viewer")
    , device_id_ (device_id)
    {}

    void
    cloud_cb_ (const CloudConstPtr& cloud)
    {
      FPS_CALC ("callback");
      set (cloud);
    }

    void
    set (const CloudConstPtr& cloud)
    {
      //lock while we set our cloud;
      boost::mutex::scoped_lock lock (mtx_);
      cloud_  = cloud;
    }

    CloudConstPtr
    get ()
    {
      //lock while we swap our cloud and reset it.
      boost::mutex::scoped_lock lock (mtx_);
      CloudConstPtr temp_cloud;
      temp_cloud.swap (cloud_);       //here we set cloud_ to null, so that
                                      //it is safe to set it again from our
                                      //callback
      return (temp_cloud);
    }

    void
    run ()
    {
      pcl::Grabber* interface = new pcl::OpenNIGrabber (device_id_);

      boost::function<void (const CloudConstPtr&)> f = boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);

      boost::signals2::connection c = interface->registerCallback (f);

      interface->start ();

      while (!viewer.wasStopped ())
      {
        if(cloud_)
        {
          FPS_CALC ("drawing");
          //the call to get() sets the cloud_ to null;
          viewer.showCloud (get ());
        }
      }

      interface->stop ();
    }

    pcl::visualization::CloudViewer viewer;
    std::string device_id_;
    boost::mutex mtx_;
    CloudConstPtr cloud_;
};

void
usage (char ** argv)
{
  std::cout << "usage: " << argv[0] << " <device_id>\n";

  openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance ();
  if (driver.getNumberDevices () > 0)
  {
    for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices (); ++deviceIdx)
    {
      cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName (deviceIdx) << ", product: " << driver.getProductName (deviceIdx)
              << ", connected: " << (int)driver.getBus (deviceIdx) << " @ " << (int)driver.getAddress (deviceIdx) << ", serial number: \'" << driver.getSerialNumber (deviceIdx) << "\'" << endl;
      cout << "device_id may be #1, #2, ... for the first second etc device in the list or" << endl
           << "                 bus@address for the device connected to a specific usb-bus / address combination (wotks only in Linux) or" << endl
           << "                 <serial-number> (only in Linux and for devices which provide serial numbers)"  << endl;
    }
  }
  else
    cout << "No devices connected." << endl;
}

int
main (int argc, char ** argv)
{
  if (argc != 2)
  {
    usage (argv);
    return 1;
  }

  std::string arg (argv[1]);

  if (arg == "--help" || arg == "-h")
  {
    usage (argv);
    return 1;
  }

  pcl::OpenNIGrabber grabber (arg);
  if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb> ())
  {
    SimpleOpenNIViewer<pcl::PointXYZRGB> v (arg);
    v.run ();
  }
  else
  {
    SimpleOpenNIViewer<pcl::PointXYZ> v (arg);
    v.run ();
  }

  return (0);
}
<|endoftext|>


<commit_before>
// TEST my fast i/o implementation
// read and write 10^6 numbers took 120 milliseconds.
// My PC: i3 2gb RAM  Centos 7, gcc 4.8.5  c++11 mode.

#include <cstdio>
#include <cstring>
#include <chrono>
#include <cstdlib>

static const int N = 1<<20;//10^6

int a[N];
int n;

char in[1<<23];

char out[1<<23];

struct scanner
{
    char const* o;
    scanner(): o(in){
        in[fread(in,1,sizeof(in)-4,stdin)] = 0;
    }
    int readInt()
    {
        unsigned u = 0, s=  0;
        while(*o && *o <= 32)++o;
        if (*o == '-')s = ~0,++o;else if (*o == '+')++o;
        while(*o >='0' && *o <='9')u = (u << 3) + (u << 1) + (*o++ -'0');
        return (u^s) + !!s;
    }

};

struct writer
{
    char * w;
    writer() : w(out){}
    ~writer(){ flush(); }
    void writeInt( int u, char c)
    {
        if (u < 0){*w++ = '-'; u = -u;}
        int v = u;
        int n = 0,m;

        do ++n; while(v/=10);
        m = n;
        while(m-->0)w[m] = u%10 + '0',u/=10;
        w+=n;
        *w++=c;
    }
    void flush(){ if (w != out) fwrite(out, 1, w - out, stdout), w  = out;}
};

struct auto_cpu_timer
{
    typedef std::chrono::high_resolution_clock ct;
    typedef ct::time_point tp;

    tp s,e;

    auto_cpu_timer(){ s = ct::now();}
    ~auto_cpu_timer(){ e = ct::now();
    long int n = std::chrono::duration_cast< std::chrono::milliseconds > ( e - s).count();

    fprintf(stderr,"\nelapsed time: %ld ms.\n", n);
    }
};

int test()
{
    auto_cpu_timer cpu_timer;

    scanner sc;
    writer pw;
    n = sc.readInt();

    for(int i = 0; i < n; ++i)a[i] = sc.readInt();

    //sort(a, a + n);

    for(int i = 0; i < n; ++i)pw.writeInt(a[i], ' ');

    return 0;
}

void writeMillionNumbers()
{
    FILE * f = fopen("input.txt", "w");
    if (f != NULL)
    {
        n = 1000*1000;
        fprintf(f, "%d\n", n);
        srand(time(NULL));
        for(int i = 0; i < n; ++i)fprintf(f, "%d ", rand());

        fclose(f);
    }
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif

        // uncomment for write 10^6 numbers

        writeMillionNumbers();

	test();

	return 0;
}
<commit_msg>Update test.cpp<commit_after>
// TEST my fast i/o implementation
// read and write 10^6 numbers took 120 milliseconds.
// My PC: i3 2gb RAM  Centos 7, gcc 4.8.5  c++11 mode.
// UPD:  printf / scanf  - took 600 milliseconds.

#include <cstdio>
#include <cstring>
#include <chrono>
#include <cstdlib>

static const int N = 1<<20;//10^6

int a[N];
int n;

char in[1<<23];

char out[1<<23];

struct scanner
{
    char const* o;
    scanner(): o(in){
        in[fread(in,1,sizeof(in)-4,stdin)] = 0;
    }
    int readInt()
    {
        unsigned u = 0, s=  0;
        while(*o && *o <= 32)++o;
        if (*o == '-')s = ~0,++o;else if (*o == '+')++o;
        while(*o >='0' && *o <='9')u = (u << 3) + (u << 1) + (*o++ -'0');
        return (u^s) + !!s;
    }

};

struct writer
{
    char * w;
    writer() : w(out){}
    ~writer(){ flush(); }
    void writeInt( int u, char c)
    {
        if (u < 0){*w++ = '-'; u = -u;}
        int v = u;
        int n = 0,m;

        do ++n; while(v/=10);
        m = n;
        while(m-->0)w[m] = u%10 + '0',u/=10;
        w+=n;
        *w++=c;
    }
    void flush(){ if (w != out) fwrite(out, 1, w - out, stdout), w  = out;}
};

struct auto_cpu_timer
{
    typedef std::chrono::high_resolution_clock ct;
    typedef ct::time_point tp;

    tp s,e;

    auto_cpu_timer(){ s = ct::now();}
    ~auto_cpu_timer(){ e = ct::now();
    long int n = std::chrono::duration_cast< std::chrono::milliseconds > ( e - s).count();

    fprintf(stderr,"\nelapsed time: %ld ms.\n", n);
    }
};

int test()
{
    auto_cpu_timer cpu_timer;

    scanner sc;
    writer pw;
    n = sc.readInt();

    for(int i = 0; i < n; ++i)a[i] = sc.readInt();

    //sort(a, a + n);

    for(int i = 0; i < n; ++i)pw.writeInt(a[i], ' ');

    return 0;
}

int test_c_i_o()
{
    auto_cpu_timer cpu_timer;

    scanf("%d",&n);
    for(int i = 0; i < n; ++i)scanf("%d",a+i); //.a[i] = sc.readInt();

    //sort(a, a + n);

    for(int i = 0; i < n; ++i) printf("%d ", a[i]);//pw.writeInt(a[i], ' ');

    return 0;
}

void writeMillionNumbers()
{
    FILE * f = fopen("input.txt", "w");
    if (f != NULL)
    {
        n = 1000*1000;
        fprintf(f, "%d\n", n);
        srand(time(NULL));
        for(int i = 0; i < n; ++i)fprintf(f, "%d ", rand());

        fclose(f);
    }
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif

        // uncomment for write 10^6 numbers

        writeMillionNumbers();

	test();

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Nico Blodow (blodow@cs.tum.edu)
 *         Radu Bogdan Rusu (rusu@willowgarage.com)
 *         Suat Gedikli (gedikli@willowgarage.com)
 *         Ethan Rublee (rublee@willowgarage.com)
 */

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/time.h> //fps calculations
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/openni_camera/openni_driver.h>
#include <vector>

#define SHOW_FPS 1
#if SHOW_FPS
#define FPS_CALC(_WHAT_) \
do \
{ \
    static unsigned count = 0;\
    static double last = pcl::getTime ();\
    if (++count == 100) \
    { \
      double now = pcl::getTime (); \
      std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" <<  std::endl; \
      count = 0; \
      last = now; \
    } \
}while(false)
#else
#define FPS_CALC(_WHAT_) \
do \
{ \
}while(false)
#endif

template <typename PointType>
class SimpleOpenNIViewer
{
public:
  typedef pcl::PointCloud<PointType> Cloud;
  typedef typename Cloud::ConstPtr CloudConstPtr;

  SimpleOpenNIViewer(pcl::OpenNIGrabber& grabber)
    : viewer("PCL OpenNI Viewer")
    , grabber_(grabber)
  {
  }

  void
  cloud_cb_ (const CloudConstPtr& cloud)
  {
    FPS_CALC ("callback");
    set (cloud);
  }

  void
  set (const CloudConstPtr& cloud)
  {
    //lock while we set our cloud;
    boost::mutex::scoped_lock lock (mtx_);
    cloud_ = cloud;
  }

  CloudConstPtr
  get ()
  {
    //lock while we swap our cloud and reset it.
    boost::mutex::scoped_lock lock(mtx_);
    CloudConstPtr temp_cloud;
    temp_cloud.swap (cloud_); //here we set cloud_ to null, so that
    //it is safe to set it again from our
    //callback
    return (temp_cloud);
  }

  void
  run()
  {
    //pcl::Grabber* interface = new pcl::OpenNIGrabber(device_id_, pcl::OpenNIGrabber::OpenNI_QQVGA_30Hz, pcl::OpenNIGrabber::OpenNI_VGA_30Hz);

    boost::function<void (const CloudConstPtr&) > f = boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);

    boost::signals2::connection c = grabber_.registerCallback (f);

    grabber_.start();

    while (!viewer.wasStopped ())
    {
      if (cloud_)
      {
        FPS_CALC ("drawing");
        //the call to get() sets the cloud_ to null;
        viewer.showCloud (get ());
      }
    }

    grabber_.stop();
  }

  pcl::visualization::CloudViewer viewer;
  pcl::OpenNIGrabber& grabber_;
  boost::mutex mtx_;
  CloudConstPtr cloud_;
};

void
usage(char ** argv)
{
  cout << "usage: " << argv[0] << " [<device_id> [<depth-mode> [<image-mode>] ] ]\n";
  cout << argv[0] << " -h | --help : shows this help" << endl;
  cout << argv[0] << " -l : list all available devices" << endl;
  cout << argv[0] << " -l <device-id> : list all available modes for specified device" << endl;

  cout << "                 device_id may be #1, #2, ... for the first, second etc device in the list"
#ifndef _WIN32
       << " or" << endl
       << "                 bus@address for the device connected to a specific usb-bus / address combination or" << endl
       << "                 <serial-number>"
#endif
       << endl;
  cout << endl;
  cout << "examples:" << endl;
  cout << argv[0] << " \"#1\"" << endl;
  cout << "    uses the first device." << endl;
  cout << argv[0] << " -l" << endl;
  cout << "    lists all available devices." << endl;
  cout << argv[0] << " -l \"#2\"" << endl;
  cout << "    lists all available modes for the second device" << endl;
  #ifndef _WIN32
  cout << argv[0] << " A00361800903049A" << endl;
  cout << "    uses the device with the serial number \'A00361800903049A\'." << endl;
  cout << argv[0] << " 1@16" << endl;
  cout << "    uses the device on address 16 at usb bus 1." << endl;
  #endif
  return;
}

int
main(int argc, char ** argv)
{
  std::string arg("");
  pcl::OpenNIGrabber::Mode depth_mode = pcl::OpenNIGrabber::OpenNI_Default_Mode;
  pcl::OpenNIGrabber::Mode image_mode = pcl::OpenNIGrabber::OpenNI_Default_Mode;

  if (argc >= 2)
  {
    arg = argv[1];

    if (arg == "--help" || arg == "-h")
    {
      usage(argv);
      return 1;
    }
    else if (arg == "-l")
    {
      if (argc >= 3)
      {
        pcl::OpenNIGrabber grabber(argv[2]);
        const openni_wrapper::OpenNIDevice& device = grabber.getDevice();
        cout << "Supported depth modes for device: " << device.getVendorName() << " , " << device.getProductName() << endl;
        std::vector<std::pair<int, XnMapOutputMode > > modes = grabber.getAvailableDepthModes();
        for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
        {
          cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << endl;
        }

        cout << endl << "Supported image modes for device: " << device.getVendorName() << " , " << device.getProductName() << endl;
        modes = grabber.getAvailableImageModes();
        for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
        {
          cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << endl;
        }
        return 0;
      }
      else
      {
        openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance();
        if (driver.getNumberDevices() > 0)
        {
          for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices(); ++deviceIdx)
          {
            cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName(deviceIdx) << ", product: " << driver.getProductName(deviceIdx)
              << ", connected: " << (int) driver.getBus(deviceIdx) << " @ " << (int) driver.getAddress(deviceIdx) << ", serial number: \'" << driver.getSerialNumber(deviceIdx) << "\'" << endl;
          }

        }
        else
          cout << "No devices connected." << endl;
        return 0;
      }
    }

    if (argc >= 3)
    {
      depth_mode = (pcl::OpenNIGrabber::Mode) atoi(argv[2]);
      if (argc == 4)
      {
        image_mode = (pcl::OpenNIGrabber::Mode) atoi(argv[3]);
      }
    }
  }
  else
  {
    openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance();
    if (driver.getNumberDevices() > 0)
      cout << "Device Id not set, using first device." << endl;
  }

  pcl::OpenNIGrabber grabber(arg, depth_mode, image_mode);
  if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb > ())
  {
    SimpleOpenNIViewer<pcl::PointXYZRGB> v(grabber);
    v.run();
  }
  else
  {
    SimpleOpenNIViewer<pcl::PointXYZI> v(grabber);
    v.run();
  }

  return (0);
}
<commit_msg>added support for ONI playback<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Nico Blodow (blodow@cs.tum.edu)
 *         Radu Bogdan Rusu (rusu@willowgarage.com)
 *         Suat Gedikli (gedikli@willowgarage.com)
 *         Ethan Rublee (rublee@willowgarage.com)
 */

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/time.h> //fps calculations
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/openni_camera/openni_driver.h>
#include <vector>

#define SHOW_FPS 1
#if SHOW_FPS
#define FPS_CALC(_WHAT_) \
do \
{ \
    static unsigned count = 0;\
    static double last = pcl::getTime ();\
    if (++count == 100) \
    { \
      double now = pcl::getTime (); \
      std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" <<  std::endl; \
      count = 0; \
      last = now; \
    } \
}while(false)
#else
#define FPS_CALC(_WHAT_) \
do \
{ \
}while(false)
#endif

template <typename PointType>
class SimpleOpenNIViewer
{
public:
  typedef pcl::PointCloud<PointType> Cloud;
  typedef typename Cloud::ConstPtr CloudConstPtr;

  SimpleOpenNIViewer(pcl::OpenNIGrabber& grabber)
    : viewer("PCL OpenNI Viewer")
    , grabber_(grabber)
  {
  }

  /**
   * @brief Callback method for the grabber interface
   * @param cloud The new point cloud from Grabber
   */
  void
  cloud_cb_ (const CloudConstPtr& cloud)
  {
    FPS_CALC ("callback");
    boost::mutex::scoped_lock lock (mtx_);
    cloud_ = cloud;
  }

  /**
   * @brief swaps the pointer to the point cloud with Null pointer and returns the cloud pointer
   * @return boost shared pointer to point cloud
   */
  CloudConstPtr
  getLatestCloud ()
  {
    //lock while we swap our cloud and reset it.
    boost::mutex::scoped_lock lock(mtx_);
    CloudConstPtr temp_cloud;
    temp_cloud.swap (cloud_); //here we set cloud_ to null, so that
    //it is safe to set it again from our
    //callback
    return (temp_cloud);
  }

  /**
   * @brief starts the main loop
   */
  void
  run()
  {
    //pcl::Grabber* interface = new pcl::OpenNIGrabber(device_id_, pcl::OpenNIGrabber::OpenNI_QQVGA_30Hz, pcl::OpenNIGrabber::OpenNI_VGA_30Hz);

    boost::function<void (const CloudConstPtr&) > f = boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);

    boost::signals2::connection c = grabber_.registerCallback (f);

    grabber_.start();

    while (!viewer.wasStopped ())
    {
      if (cloud_)
      {
        FPS_CALC ("drawing");
        //the call to get() sets the cloud_ to null;
        viewer.showCloud (getLatestCloud ());
      }
    }

    grabber_.stop();
  }

  pcl::visualization::CloudViewer viewer;
  pcl::OpenNIGrabber& grabber_;
  boost::mutex mtx_;
  CloudConstPtr cloud_;
};

void
usage(char ** argv)
{
  cout << "usage: " << argv[0] << " [<device_id> [<depth-mode> [<image-mode>] ] ] | [path-to-oni-file]\n";
  cout << argv[0] << " -h | --help : shows this help" << endl;
  cout << argv[0] << " -l : list all available devices" << endl;
  cout << argv[0] << " -l <device-id> : list all available modes for specified device" << endl;

  cout << "                 device_id may be #1, #2, ... for the first, second etc device in the list"
#ifndef _WIN32
       << " or" << endl
       << "                 bus@address for the device connected to a specific usb-bus / address combination or" << endl
       << "                 <serial-number>"
#endif
       << endl;
  cout << endl;
  cout << "examples:" << endl;
  cout << argv[0] << " \"#1\"" << endl;
  cout << "    uses the first device." << endl;
  cout << argv[0] << " \"./temp/test.oni\"" << endl;
  cout << "    uses the oni-player device to play back oni file given by path." << endl;
  cout << argv[0] << " -l" << endl;
  cout << "    lists all available devices." << endl;
  cout << argv[0] << " -l \"#2\"" << endl;
  cout << "    lists all available modes for the second device" << endl;
  #ifndef _WIN32
  cout << argv[0] << " A00361800903049A" << endl;
  cout << "    uses the device with the serial number \'A00361800903049A\'." << endl;
  cout << argv[0] << " 1@16" << endl;
  cout << "    uses the device on address 16 at usb bus 1." << endl;
  #endif
  return;
}

int
main(int argc, char ** argv)
{
  std::string arg("");
  pcl::OpenNIGrabber::Mode depth_mode = pcl::OpenNIGrabber::OpenNI_Default_Mode;
  pcl::OpenNIGrabber::Mode image_mode = pcl::OpenNIGrabber::OpenNI_Default_Mode;

  if (argc >= 2)
  {
    arg = argv[1];

    if (arg == "--help" || arg == "-h")
    {
      usage(argv);
      return 1;
    }
    else if (arg == "-l")
    {
      if (argc >= 3)
      {
        pcl::OpenNIGrabber grabber(argv[2]);
        const openni_wrapper::OpenNIDevice& device = grabber.getDevice();
        cout << "Supported depth modes for device: " << device.getVendorName() << " , " << device.getProductName() << endl;
        std::vector<std::pair<int, XnMapOutputMode > > modes = grabber.getAvailableDepthModes();
        for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
        {
          cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << endl;
        }

        cout << endl << "Supported image modes for device: " << device.getVendorName() << " , " << device.getProductName() << endl;
        modes = grabber.getAvailableImageModes();
        for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
        {
          cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << endl;
        }
        return 0;
      }
      else
      {
        openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance();
        if (driver.getNumberDevices() > 0)
        {
          for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices(); ++deviceIdx)
          {
            cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName(deviceIdx) << ", product: " << driver.getProductName(deviceIdx)
              << ", connected: " << (int) driver.getBus(deviceIdx) << " @ " << (int) driver.getAddress(deviceIdx) << ", serial number: \'" << driver.getSerialNumber(deviceIdx) << "\'" << endl;
          }

        }
        else
          cout << "No devices connected." << endl;

        cout <<"Virtual Devices available: ONI player" << endl;
        return 0;
      }
    }

    if (argc >= 3)
    {
      depth_mode = (pcl::OpenNIGrabber::Mode) atoi(argv[2]);
      if (argc == 4)
      {
        image_mode = (pcl::OpenNIGrabber::Mode) atoi(argv[3]);
      }
    }
  }
  else
  {
    openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance();
    if (driver.getNumberDevices() > 0)
      cout << "Device Id not set, using first device." << endl;
  }

  pcl::OpenNIGrabber grabber(arg, depth_mode, image_mode);
  if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb > ())
  {
    SimpleOpenNIViewer<pcl::PointXYZRGB> v(grabber);
    v.run();
  }
  else
  {
    SimpleOpenNIViewer<pcl::PointXYZI> v(grabber);
    v.run();
  }

  return (0);
}
<|endoftext|>