예제 #1
0
void turbodisk_buffer(uint8_t *data, uint8_t length) {
  unsigned int pair;
  uint32_t ticks;

  fastloader_setup();

  /* wait for handshake */
  while (IEC_DATA) ;
  set_clock(1);
  wait_data(1, NO_ATNABORT);

  ticks = 70;
  while (length--) {
    uint8_t byte = *data++;

    ticks += 120;
    for (pair = 0; pair < 4; pair++) {
      ticks += 240;
      set_clock_at(ticks, byte & 0x80, NO_WAIT);
      set_data_at (ticks, byte & 0x40, WAIT);
      ticks += 50;
      byte <<= 2;
    }
    ticks += 100;
  }

  ticks += 110;

  set_clock_at(ticks, 0, NO_WAIT);
  set_data_at( ticks, 1, WAIT);
  delay_us(5);

  fastloader_teardown();
}
예제 #2
0
파일: g2_ide.c 프로젝트: DC-SWAT/DreamShell
/* Write n sectors to the hard disk using PIO mode */
static int ide_write_chs(uint32 cyl,uint32 head,uint32 sector,uint32 numsects, uint8 *bufptr) {
	int	o;
	uint16	*bufptr16 = (uint16*)bufptr;

	//printf("writing C/H/S/Cnt %d/%d/%d/%d\n",
	//	cyl, head, sector, numsects);

	wait_controller();		/* wait for controller to be not busy */

	outp(0x1f2,numsects & 0xff);	/* number of sectors to write */
	outp(0x1f3,sector & 0xff);	/* sector number to write */
	outp(0x1f4,cyl & 0xff);		/* cylinder (low part) */
	outp(0x1f5,cyl >> 8);		/* cylinder (high part) */
	outp(0x1f6,0xa0 | (head&0xf));	/* select device 0 and head */
	outp(0x1f7,0x30);		/* command == write sector(s) w/retry */

	wait_data();			/* wait for data to be ready */

	for (o=0; o<256; o++) {
		/* if (inp(0x1f7) & 1) {
			printf("as of %d, error code is %x/%x\n", o, inp(0x1f7), inp(0x1f1));
			return -1;
		} */
		outpw(0x1f0, bufptr16[o]);
	}
/*
	if (inp(0x1f7) & 1) {
		printf("after write, status is %x/%x\n", inp(0x1f7), inp(0x1f1));
	}
*/
	return 0;
}
예제 #3
0
파일: ocheck.c 프로젝트: ocedo/ocheck
static int write_retry(int fd, uint8_t *buf, uint32_t buf_len)
{
	int len = 0;

	do {
		int cur_len;

		cur_len = write(fd, &buf[len], buf_len - len);
		if (cur_len < 0) {
			switch(errno) {
			case EAGAIN:
				wait_data(fd, true);
				break;
			case EINTR:
				break;
			default:
				return -1;
			}
			continue;
		}
		if (curr_flush_state != BUSY)
			return 0;

		len += cur_len;
		if (len == buf_len)
			return len;

	} while (1);

	/* Should never reach here */
	return -1;
}
예제 #4
0
uint8_t epyxcart_send_byte(uint8_t byte) {
  uint8_t result = 0;

  fastloader_setup();
  disable_interrupts();

  /* clear bus */
  set_data(1);
  set_clock(1);
  delay_us(3);

  /* wait for start signal */
  wait_data(1, ATNABORT);
  if (!IEC_ATN) {
    result = 1;
    goto exit;
  }

  /* transmit data */
  generic_load_2bit(&epyxcart_send_def, byte);

  /* data hold time */
  delay_us(20);

 exit:
  disable_interrupts();
  fastloader_teardown();
  return result;
}
예제 #5
0
int16_t uload3_get_byte(void) {
  uint8_t result;

  /* initial handshake */
  set_clock(0);
  while (IEC_DATA && IEC_ATN) ;
  if (!IEC_ATN)
    return -1;

  fastloader_setup();
  disable_interrupts();

  /* wait for start signal */
  set_clock(1);
  wait_data(1, NO_ATNABORT);

  /* receive data */
  result = generic_save_2bit(&uload3_get_def);

  /* wait until the C64 releases the bus */
  delay_us(20);

  enable_interrupts();
  fastloader_teardown();
  return result;
}
예제 #6
0
uint8_t jiffy_send(uint8_t value, uint8_t eoi, uint8_t loadflags) {
  unsigned int loadmode = loadflags & 0x80;
  unsigned int skipeoi  = loadflags & 0x7f;

  fastloader_setup();
  disable_interrupts();

  /* Initial handshake */
  set_data(1);
  set_clock(1);
  delay_us(3);

  if (loadmode) {
    /* LOAD mode: start marker is data low */
    while (!IEC_DATA) ; // wait until data actually is high again
    wait_data(0, ATNABORT);
  } else {
    /* single byte mode: start marker is data high */
    wait_data(1, ATNABORT);
  }

  /* transmit data */
  generic_load_2bit(&jiffy_send_def, value);

  /* Send EOI info */
  if (!skipeoi) {
    if (eoi) {
      set_clock_at(520, 1, NO_WAIT);
      set_data_at (520, 0, WAIT);
    } else {
      /* LOAD mode also uses this for the final byte of a block */
      set_clock_at(520, 0, NO_WAIT);
      set_data_at (520, 1, WAIT);
    }

    /* wait until data is low */
    delay_us(3); // allow for slow rise time
    while (IEC_DATA && IEC_ATN) ;
  }

  /* hold time */
  delay_us(10);

  enable_interrupts();
  fastloader_teardown();
  return !IEC_ATN;
}
예제 #7
0
void *receive_arp( void *ptr ) {
  int sd, status;
  char ether_frame[ETH_FRAME_ARP];
  struct ifaddrs *local_endpoint = *((struct ifaddrs **)(ptr));
  thrash_t *addrs = *((thrash_t **)(ptr)+1);
  if ((sd = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
    perror ("socket() failed ");
    return NULL;
  }

  if ( !quiet ) printf("IP-address\tMAC-address\n");

  while ( !_rec_exit ) {
    delete_frame_type(ether_frame);
    arp_hdr *arphdr_rec = alloc_arphdr(ether_frame);
    while ( ( !is_frame_arp(ether_frame) ||
              !is_arp_reply(arphdr_rec) ) &&
            !_rec_exit ) {
      if (wait_data(sd) < 0) {
        fprintf(stderr, "wait socket data error\n");
        return NULL;
      } else if ( _rec_exit ) return NULL;
      if ((status = recv (sd, ether_frame, ETH_FRAME_ARP, 0)) < 0) {
        if (errno == EINTR) {
          memset (ether_frame, 0, ETH_FRAME_ARP);
          continue;
        } else {
          perror ("recv() failed: ");
          return NULL;
        }
      }
    }
    if ( !is_source_mac(ether_frame, (char*)ifaddr_mac(local_endpoint)) ) continue;

    if ( chain_del_value(addrs, ntohl(arphdr_rec->sender_ip)) ) {
      if ( !quiet ) {
        printf ("%s\t[", inet_ntoa(int_in_addr(arphdr_rec->sender_ip)));
        print_macstr(arphdr_rec->sender_mac);
        printf("]\n");
      }
    }
  }

  return NULL;
}
예제 #8
0
void turbodisk_byte(uint8_t value) {
  fastloader_setup();

  /* wait for handshake */
  while (IEC_DATA) ;
  set_clock(1);
  wait_data(1, NO_ATNABORT);

  /* transmit data */
  generic_load_2bit(&turbodisk_byte_def, value);

  /* exit with clock low, data high */
  set_clock_at(1470, 0, NO_WAIT);
  set_data_at( 1470, 1, WAIT);
  delay_us(5);

  fastloader_teardown();
}
예제 #9
0
void ar6_1581_send_byte(uint8_t byte) {
  fastloader_setup();
  disable_interrupts();

  /* wait for handshake */
  set_clock(1);
  wait_data(1, NO_ATNABORT);

  /* transmit data */
  generic_load_2bit(&ar6_1581_send_def, byte);

  /* exit with clock low, data high */
  set_clock_at(375, 0, NO_WAIT);
  set_data_at( 375, 1, WAIT);

  /* short delay to make sure bus has settled */
  delay_us(10);

  enable_interrupts();
  fastloader_teardown();
}
예제 #10
0
uint8_t ar6_1581p_get_byte(void) {
  uint8_t result;

  fastloader_setup();
  disable_interrupts();

  set_clock(1);

  /* wait for handshake */
  while (IEC_DATA) ;
  wait_data(1, NO_ATNABORT);

  /* receive data */
  result = generic_save_2bit(&ar6_1581p_get_def);

  /* exit with clock low */
  set_clock_at(530, 0, WAIT);

  enable_interrupts();
  fastloader_teardown();
  return result;
}
예제 #11
0
파일: g2_ide.c 프로젝트: DC-SWAT/DreamShell
/* Initialize the device */
int ide_init() {
	int dd_off;
	
	//dbglog(DBG_INFO, "ide_init: initializing\n");

	/* Reset */
	outp(0x3f6, 0x0e);
	thd_sleep(10);
	outp(0x3f6, 0x0a);
	thd_sleep(10);

	if(wait_controller() < 0) {
		return -1;
	}
	
	outp(0x1f6,0xa0);	/* get info on first drive. 0xb0 == 2nd */
	outp(0x1f7,0xec);	/* get drive info data */
	
	if(wait_data() < 0) {
		return -1;
	}
	
	for (dd_off=0; dd_off<256; dd_off++) {
		dd[dd_off] = inpw(0x1f0);
	}

	hd_cyls = dd[1];
	hd_heads = dd[3];
	hd_sects = dd[6];

	ds_printf("DS_IDE: Detected %s, %dMB, CHS (%d/%d/%d)\n",
	get_ascii(dd, 27, 46),
	(hd_cyls * hd_heads * hd_sects * 512L) / (1024L*1024L),
	hd_cyls, hd_heads, hd_sects);

	return 0;
}
예제 #12
0
파일: ocheck.c 프로젝트: ocedo/ocheck
static __attribute__((destructor(101))) void ocheck_fini()
{
	uint32_t flushed = 0;
	const char *proc_name;

	/* Prevent forks from calling de-init code */
	if (!lib_inited || pid != ourgetpid())
		return;

	backtraces_set_max_backtraces(0);
	if (!(proc_name = is_this_the_right_proc()))
		goto out;

	debug("Uninitializing libocheck.so for %s.%u...\n", proc_name, pid);

	if (fd > -1) {
		if (curr_flush_state == BUSY) {
			debug("  Flushing still in progress...\n");
			curr_flush_state = INTERRUPT;
			while (curr_flush_state != IDLE)
				wait_data(fd, true);
		}

		flushed = flush_messages(true);
		close(fd);
	}

	debug("  Flushed %u messages\n", flushed);

	if (pid > -1 && flushed)
		kill(pid, SIGSEGV);

	debug("Done\n");
out:
	lib_inited = false;
}
예제 #13
0
static void test_tcp_server(void)
{
	int re;
	int sd;
	int reader = 0;
	char buf[5];
	struct sockaddr_in sa;
	struct sockaddr_in sa2;
	socklen_t sa_len;

	printf("[tcp(server)] start\n");

	sd = so_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if ( sd < 0 ) {
		goto error;
	}
	DEBUG_PRINT(("server_task: so_socket = %d(%d, %d)\n", sd, MERCD(sd), SERCD(sd)));

	bzero(&sa, sizeof sa);
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = htonl(INADDR_ANY);
	sa.sin_port = htons(12345);
	re = so_bind(sd, (struct sockaddr*)&sa, sizeof sa);
	DEBUG_PRINT(("server_task: so_bind = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}

	re = so_listen(sd, 5);
	DEBUG_PRINT(("server_task: so_listen = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}

	tk_sig_sem(semid, 1);
	DEBUG_PRINT(("server_task: server semaphore signaled 1\n"));

	reader = so_accept(sd, (struct sockaddr*)&sa2, &sa_len);
	DEBUG_PRINT(("server_task: so_accept = %d(%d, %d)\n", reader, MERCD(reader), SERCD(reader)));
	if ( reader < 0 ) {
		goto error;
	}

	wait_data(reader);

	bzero(buf, sizeof buf);
	re = so_sockatmark(reader);
	DEBUG_PRINT(("server_task: so_sockatmark = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}
	re = so_read(reader, buf, 4);
	DEBUG_PRINT(("server_task: so_read = %d(%d, %d), buf = %s\n", re, MERCD(re), SERCD(re), buf));
	if ( re < 0 || memcmp(buf, "1234", 4) != 0 ) {
		goto error;
	}

	wait_data(reader);

	bzero(buf, sizeof buf);
	re = so_sockatmark(reader);
	DEBUG_PRINT(("server_task: so_sockatmark = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}
	re = so_recv(reader, buf, 4, MSG_OOB);
	DEBUG_PRINT(("server_task: so_recv = %d(%d, %d), buf = %s\n", re, MERCD(re), SERCD(re), buf));
	if ( re < 0 || buf[0] != 'a' ) {
		goto error;
	}

	tk_sig_sem(semid2, 1);
	DEBUG_PRINT(("server_task: server semaphore for break signaled 2\n"));

	DEBUG_PRINT(("server_task: pre-accept for break\n"));
	re = so_accept(sd, (struct sockaddr*)&sa2, &sa_len);
	DEBUG_PRINT(("server_task: so_accept = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re != EX_INTR ) {
		goto error;
	}

	so_close(reader);
	so_close(sd);

	printf("[tcp(server)] OK\n");
	return;

error:
	printf("[tcp(server)] FAILED\n");
	if ( sd > 0 ) {
		so_close(sd);
	}
	if ( reader > 0 ) {
		so_close(reader);
	}
	tk_del_sem(semid2);
	return;
}
예제 #14
0
/*---------------------------------------------------------------------------
  Main program start here
 *---------------------------------------------------------------------------*/
int main() 
{
  GPIO_InitTypeDef pa0;
  
  RCC_RTC_Configuration();
  LCD_GLASS_Init();
  LCD_GLASS_Configure_GPIO();
  
  init_USART();
  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
  
  GPIO_StructInit(&pa0);
  pa0.GPIO_Mode = GPIO_Mode_IN;
  pa0.GPIO_Pin = GPIO_Pin_0;
  GPIO_Init(GPIOA,&pa0);

    while(1) {
    if( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1 && state == 0)
    {
      count++;
      sprintf(DataSendToServer,"GET /cpe312/index.php?Name=TESTING_%d HTTP/1.1\r\nHost: markdang.lnw.mn\r\n\r\n",count);
      
      // Test AT startup
      send_data("AT\r\n");
      wait_data("OK");
      
      // Restart module
      send_data("AT+RST\r\n");
      wait_data("ready");

      display("OK RST");
   
      // Set Station & softAP Mode
      send_data("AT+CWMODE_CUR=3\r\n");
      wait_data("OK");
      display("STA+AP");
      
      // Set Station & softAP Mode
      send_data("AT+CWJAP_CUR=\"CPE312\",\"25033333\"\r\n");
      wait_data("OK");
      display("SET AP");
      
      // Set TCP , Address & Port : Check data http://markdang.lnw.mn/cpe312/show_data.php
      send_data("AT+CIPSTART=\"TCP\",\"markdang.lnw.mn\",80\r\n");
      wait_data("CONNECT");
      display("SETTCP");
      
      length = strlen(DataSendToServer);  // find length of data
      sprintf(nbr_DataSendToServer, "AT+CIPSEND=%d\r\n", length); // Set data size
      
      // Send length of data to server
      send_data(nbr_DataSendToServer);
      wait_data(">");
      display("SetLEN");
      
      // Send data to server
      send_data(DataSendToServer);
      wait_data("SEND OK");
      display("SENDOK");
      
      // Close AP
      send_data("AT+CWQAP\r\n");
      wait_data("OK");
      display("Close");
      
      state = 1;
    }
    else if ( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0 && state == 1)
    {
      state = 0;
    }
    display("ready ");
    }
}
예제 #15
0
void websocket_hybi_17::on_frame_payload(boost::system::error_code err, size_t bytes_transferred)
{
	if ( is_closed(err, bytes_transferred) )
	{
		return;
	}

	if ( !check_err(err, "frame read") ||
		 !check_err(bytes_transferred == payload_len_, "frame read") )
	{
		return;
	}

	bool const is_final_fragment = (frame_start_[0] & 0x80) != 0;
	if ( is_final_fragment )
	{
		read_buf_.commit(bytes_transferred);
	}

	uint8_t const opcode = (frame_start_[0] & 0x0F);

	if ( !check_err(is_final_fragment || !opcode, "Invalid continuation frame") )
	{
		return;
	}

	if ( opcode & 0x8 )
	{
		// control opcode
		if ( !check_err(payload_len_ < 126 && is_final_fragment, "Invalid control frame") )
		{
			return;
		}
	}

	switch ( opcode )
	{
	case opcodes::CONTINUATION:
		check_err(!is_final_fragment, "Invalid continuation frame");
		break;
	case opcodes::TEXT:
		handle_data(false);
		break;
	case opcodes::BINARY:
		handle_data(true);
		break;
	case opcodes::CLOSE:
		handle_close();
		break;
	case opcodes::PING:
		break;
	case opcodes::PONG:
		// do nothing
		break;
	default:
		check_err(false, "Unknown frame type");
		break;
	}

	wait_data();
}
예제 #16
0
bool websocket_hybi_17::handshake(url const& target)
{
	_aspect_assert(state() == CONNECTING);

	// create websocket handshake request
	pion::http::request req(target.path_for_request());

	req.add_header("Connection", "Upgrade");
	req.add_header("Upgrade", "WebSocket");

	req.add_header("Host", target.hostport());
	req.add_header("Origin", target.origin());

	string key(16, 0);
	std::generate(key.begin(), key.end(), rand_byte);
	string encoded_key;
	if ( !pion::algorithm::base64_encode(key, encoded_key) )
	{
		return false;
	}
	req.add_header("Sec-WebSocket-Key", encoded_key);
	req.add_header("Sec-WebSocket-Version", "13");

	// send request, recieve response
	error_code err = send_message(req);
	if ( !check_err(err, "send request") )
	{
		return false;
	}

	pion::http::response resp(req);
	resp.receive(*tcp_conn_, err);
	if ( !check_err(err, "recieve response") )
	{
		return false;
	}

	// check response
	if ( !is_websocket_upgrade(resp) )
	{
		// it is not a hybi connection upgrade, give a chance for another protocol
		return false;
	}

	// Check reply key
	encoded_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
	encoded_key = crypto::sha1_digest(encoded_key.data(), encoded_key.size());
	string resp_key;
	if ( !pion::algorithm::base64_encode(encoded_key, resp_key) )
	{
		return false;
	}

	if ( resp_key != resp.get_header("Sec-WebSocket-Accept") )
	{
		return false;
	}

	state_ = OPEN;
	on_connect(target.to_string());
	wait_data();

	return true;
}
예제 #17
0
bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
{
	init_args(game_params, cmd_args);

	// List video modes if requested
	if (list_video_modes)
		return print_video_modes();

	if (!init_engine()) {
		errorstream << "Could not initialize game engine." << std::endl;
		return false;
	}

	// Create time getter
	g_timegetter = new IrrlichtTimeGetter(device);

	// Speed tests (done after irrlicht is loaded to get timer)
	if (cmd_args.getFlag("speedtests")) {
		dstream << "Running speed tests" << std::endl;
		speed_tests();
		return true;
	}

	video::IVideoDriver *video_driver = device->getVideoDriver();
	if (video_driver == NULL) {
		errorstream << "Could not initialize video driver." << std::endl;
		return false;
	}

	porting::setXorgClassHint(video_driver->getExposedVideoData(), PROJECT_NAME_C);

	/*
		This changes the minimum allowed number of vertices in a VBO.
		Default is 500.
	*/
	//driver->setMinHardwareBufferVertexCount(50);
	video_driver->setMinHardwareBufferVertexCount(100);

	// Create game callback for menus
	g_gamecallback = new MainGameCallback(device);

	device->setResizable(true);

	if (random_input)
		input = new RandomInputHandler();
	else
		input = new RealInputHandler(device, receiver);

	smgr = device->getSceneManager();
	smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);

	guienv = device->getGUIEnvironment();
	skin = guienv->getSkin();

	skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255));
	skin->setColor(gui::EGDC_3D_LIGHT, video::SColor(0, 0, 0, 0));
	skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 30, 30, 30));
	skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0));
	skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 56, 121, 65));
	skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255));


#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
	// Irrlicht 1.8 input colours
	skin->setColor(gui::EGDC_EDITABLE, video::SColor(255, 128, 128, 128));
	skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255, 97, 173, 109));
#endif

	// Create the menu clouds
	if (!g_menucloudsmgr)
		g_menucloudsmgr = smgr->createNewSceneManager();
	if (!g_menuclouds)
		g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(),
				g_menucloudsmgr, -1, rand(), 100);
	g_menuclouds->update(v2f(0, 0), video::SColor(255, 200, 200, 255));
	scene::ICameraSceneNode* camera;
	camera = g_menucloudsmgr->addCameraSceneNode(0,
				v3f(0, 0, 0), v3f(0, 120, 100));
	camera->setFarValue(10000);

#ifdef __ANDROID__
	wait_data();
#endif

	g_fontengine = new FontEngine(g_settings, guienv);
	FATAL_ERROR_IF(g_fontengine == NULL, "Font engine creation failed.");

	/*
		GUI stuff
	*/

	ChatBackend chat_backend;

	// If an error occurs, this is set to something by menu().
	// It is then displayed before the menu shows on the next call to menu()
	std::string error_message;
	bool reconnect_requested = false;

	bool first_loop = true;

	/*
		Menu-game loop
	*/
	bool retval = true;
	bool *kill = porting::signal_handler_killstatus();

	while (device->run() && !*kill && !g_gamecallback->shutdown_requested)
	{
		// Set the window caption
		const wchar_t *text = wgettext("Main Menu");
		device->setWindowCaption((utf8_to_wide(PROJECT_NAME_C) + L" [" + text + L"]").c_str());
		delete[] text;

		try {	// This is used for catching disconnects

			guienv->clear();

			/*
				We need some kind of a root node to be able to add
				custom gui elements directly on the screen.
				Otherwise they won't be automatically drawn.
			*/
			guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000));

			bool game_has_run = launch_game(error_message, reconnect_requested,
				game_params, cmd_args);

			// Reset the reconnect_requested flag
			reconnect_requested = false;

			// If skip_main_menu, we only want to startup once
			if (skip_main_menu && !first_loop)
				break;

			first_loop = false;

			if (!game_has_run) {
				if (skip_main_menu)
					break;
				else
					continue;
			}

			if (g_settings_path != "")
				g_settings->updateConfigFile(g_settings_path.c_str());

			// Break out of menu-game loop to shut down cleanly
			if (!device->run() || *kill) {
				break;
			}

/*
			if (current_playername.length() > PLAYERNAME_SIZE-1) {
				error_message = gettext("Player name too long.");
				playername = current_playername.substr(0, PLAYERNAME_SIZE-1);
				g_settings->set("name", playername);
				continue;
			}
*/

			device->getVideoDriver()->setTextureCreationFlag(
					video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map"));

#ifdef HAVE_TOUCHSCREENGUI
		if (g_settings->getBool("touchscreen")) {
			receiver->m_touchscreengui = new TouchScreenGUI(device, receiver);
			g_touchscreengui = receiver->m_touchscreengui;
		}
#endif
			int tries = simple_singleplayer_mode ? 1 : g_settings->getU16("reconnects");
			int n = 0;

			while(!*kill && ++n <= tries &&
			the_game(
				kill,
				random_input,
				input,
				device,
				worldspec.path,
				current_playername,
				current_password,
				current_address,
				current_port,
				error_message,
				chat_backend,
				&reconnect_requested,
				gamespec,
				simple_singleplayer_mode
				, autoexit
			)
			){
				smgr->clear();
				errorstream << "Reconnecting "<< n << "/" << tries << " ..." << std::endl;
			}
			smgr->clear();

#ifdef HAVE_TOUCHSCREENGUI
			delete g_touchscreengui;
			g_touchscreengui = NULL;
			receiver->m_touchscreengui = NULL;
#endif

		} //try
		catch (con::PeerNotFoundException &e) {
			error_message = _("Connection error (timed out?)");
			errorstream << error_message << std::endl;
		}

#if !EXEPTION_DEBUG
		catch (std::exception &e) {
			std::string error_message = "Some exception: \"";
			error_message += e.what();
			error_message += "\"";
			errorstream << error_message << std::endl;
		}
#endif

		// If no main menu, show error and exit
		if (skip_main_menu) {
			if (!error_message.empty()) {
				verbosestream << "error_message = "
				              << error_message << std::endl;
				retval = false;
			}
			break;
		}
	} // Menu-game loop

	g_menuclouds->drop();
	g_menucloudsmgr->drop();

#ifdef _IRR_COMPILE_WITH_LEAK_HUNTER_
	auto objects = LeakHunter::getReferenceCountedObjects();
	infostream<<"irrlicht leaked objects="<<objects.size()<<std::endl;
	for (unsigned int i = 0; i < objects.size(); ++i) {
		if (!objects[i])
			continue;
		infostream<<i<<":" <<objects[i]<< " cnt="<<objects[i]->getReferenceCount()<<" desc="<<(objects[i]->getDebugName() ? objects[i]->getDebugName() : "")<<std::endl;
	}
#endif

	return retval;
}