Beispiel #1
0
void logError(const char *fmt, ...) {
	LockID lock = Thread.EnterLock(MUTEX_LOG);
	FILE *logfile = NULL; va_list ap;

	logfile = fopen("opengta2.log", "a");

	va_start(ap, fmt);
	if (logfile) fprintf(logfile,"[%.3f] Error: ",curtime());
	printf("[%.3f] Error: ",curtime());

	//Print to log history
	#ifndef DEDICATED_SERVER
		char text[8192]; 
		vsnprintf(text,8192,fmt,ap);
		Console.printf("\003%s\n",text);
	#endif

	if (logfile) vfprintf(logfile, fmt, ap);
	vprintf(fmt, ap);
	va_end(ap); 
	
	if (logfile) fprintf(logfile, "\n"); 
	printf("\n");

	if (logfile) fclose(logfile);
	breakpoint();
	Thread.LeaveLock(lock);
}
Beispiel #2
0
void debugTestTimerLoop(float FPSLimit, float interval) {
	logWrite("FPS must be %.2f. dT must be %.4f seconds",FPSLimit,interval);

	logDisableDebugOutput = true;

	float startTime = curtime();
	int startFrames = Timer.totalFrames;

	Timer.Frame(); //First frame
	Timer.FPSLimit = FPSLimit;
	while ((curtime() - startTime < 2.0f) && (Timer.totalFrames - startFrames < 64)) {
		Thread.Sleep(interval);
		Timer.Frame();
		logWrite("Time: %.8f sec; dT: %.8f; FPS: %.4f",Timer.Time(),Timer.dT(),Timer.FPS());
		
		if (abs(Timer.dT() - interval) > 0.1f) {
			logError("Timer test failed: dT difference too high (> d0.1 sec)");
			return;
		}
		if ((FPSLimit > 0) && (abs(Timer.FPS() - FPSLimit) > 0.05f * FPSLimit)) {
			logError("Timer test failed: FPS difference too high (>5%, >%.5f sec)",0.05f * FPSLimit);
			return;
		}
	}

	logDisableDebugOutput = false;
}
Beispiel #3
0
void logWritem(const char *fmt, ...) {
#ifdef _DEBUG
	LockID lock = Thread.EnterLock(MUTEX_LOG);
	FILE *logfile = NULL; va_list ap;

	logfile = fopen("opengta2.log", "a");

	va_start(ap, fmt);
	if (logfile) fprintf(logfile,"[%.3f] \t",curtime());
	if (!logDisableDebugOutput) printf("[%.3f] \t",curtime());

	//Print to log history
	#ifndef DEDICATED_SERVER
		char text[8192]; 
		vsnprintf(text,8192,fmt,ap);
		Console.printf("\001%s\n",text);
	#endif

	if (logfile) vfprintf(logfile, fmt, ap);
	if (!logDisableDebugOutput) vprintf(fmt, ap);
	va_end(ap); 
	
	if (logfile) fprintf(logfile, "\n"); 
	if (!logDisableDebugOutput) printf("\n");

	if (logfile) fclose(logfile);
	Thread.LeaveLock(lock);
#endif
}
Beispiel #4
0
int main()
{
    long long aisz, aosz;
    double dt;
    double t0, t1, t2;
    char *buf;
    int i;

//	t0=clock();
    t0=curtime();
    aisz=0;
    buf=malloc(1<<20);
    while(!feof(stdin))
//	while(1)
    {
        i=fread(buf, 1, 1<<20, stdin);
        aisz+=1<<20;
        t1=curtime();
        t2=t1-t0;
        dt=t2;

        fprintf(stderr, "%.3fMB/s %.3f   \r",
                (aisz/(1024.0*1024.0))/dt, dt);
//		fprintf(stderr, "%.3fMB/s %.3f(%d)   \r",
//			(aisz/(1024.0*1024.0))/dt, dt, t2);
    }
    printf("\n");
    printf("dt=%.3fs\n", dt);
}
Beispiel #5
0
void test_mydifftime()
{
    struct timeval begin, end;

    curtime(&begin);
    usleep(5);
    curtime(&end);
    printf("Time Diff:%llu\n", mydifftime(&begin, &end));
}
Beispiel #6
0
void *worker(void *arg) {
  struct state *s = arg;
  s->workfn = s->opi & MFwrt ? wwriter : wreader;
  s->posfn  = s->opi & MFrnd ? randpos : linpos;
  s->fd = open(fn, (s->opi & MFwrt ? O_WRONLY : O_RDONLY) | oflags);
  if (s->fd < 0) {
    int e = errno;
    decnr();
    errno = e;
    edie(fn);
  }
  s->stime = curtime();
  for(;;) {
    if (term) break;
    if (s->workfn(s, s->posfn(s)) < 0) {
      perror(ion[s->opi]);
      break;
    }
    ++s->ioc;
    incc();
    if (bm && s->ioc >= bm) break;
  }
  decnr();
  return 0;
}
Beispiel #7
0
int enqueue(queue_t *q, RTP_header *h, unsigned ft, unsigned char *p, unsigned l, unsigned scale)
{
  unsigned j = 0;
  double t = h->timestamp / (double)scale;

  if (q->mode & MODE_STREAM || .99 * t <= curtime()) {
    if (!lock(&q->lock)) return 0;

    if (l > sizeof q->packets[q->s].p) goto PS;
    while (j++ < q->n && q->packets[q->s].blocked) INC(q);
    if (q->packets[q->s].blocked) goto PS;

    q->packets[q->s].id      = h->id;
    q->packets[q->s].tstamp  = t;
    q->packets[q->s].frame   = ft;
    q->packets[q->s].size    = l;
    q->packets[q->s].next    = 0;
    q->packets[q->s].prev    = 0;
    q->packets[q->s].blocked = 1;
    memcpy(q->packets[q->s].p, p, l);

    addpacket(q, &q->packets[q->s]);
    INC(q);

    unlock(&q->lock);
    return 1;
  } else {
    return 0;
  }

PS: seterror(err_PS);
    unlock(&q->lock);
    return 0;
}
Beispiel #8
0
void lprintf(char *fmt, ...) {
        va_list ap;
        char buf[1024], *prefix;

	FILE *out;

	/* CRITICAL SECTION */
	pthread_mutex_lock(&log_mutex);

        va_start(ap, fmt);
        vsnprintf(buf, sizeof(buf), fmt, ap);
        va_end(ap);

	prefix = curtime();
	out = log_fp;

	if (!out) {
		prefix = "***";
		out = stdout;
	}
	
        fprintf(out, "[%s] %s", prefix, buf);
        fflush(out);

	pthread_mutex_unlock(&log_mutex);
	/* CRITICAL SECTION */

        return ;
}
Beispiel #9
0
// calculates the avg. fps and simulation rate once every NITER iterations
// returns a simrate and fps of -1 for the first NITER iterations
void framerate(long simtime, double *simrate, int *fps)
{
    int j;
    static int i = 0;
    static long frmtime = -1;
    static double simsum = -1, frmsum = -1;
    static long simtimes[NITER], frmtimes[NITER];
    struct timespec now;
    static struct timespec markt;

    now = curtime();
    if (markt.tv_sec == 0 && markt.tv_nsec == 0)
        markt = now;
    else {
        frmtime = convtns(tdiff(now, markt));
        markt = now;

        simtimes[i] = simtime;
        frmtimes[i++] = frmtime;

        if (i == NITER) {
            simsum = frmsum = 0;
            for (j = 0; j < NITER; j++) {
                simsum += simtimes[j];
                frmsum += frmtimes[j];
            }
            i = 0;
        }
    }

    *simrate = (simsum == -1) ? -1 : (double) simsum / frmsum;
    *fps = (frmsum == -1) ? -1 : round((double) 1e9 * NITER / frmsum);

}
Beispiel #10
0
void request_slot(int i) {
	requested_slot = i;
	request_sent_time = curtime();
	char buffer[32];
	sprintf(buffer, "omg req %i", i);
	state = STATE_REQUESTED;
	send_msg(buffer);
}
Beispiel #11
0
void logStart() {
	FILE* logfile = fopen("opengta2.log","w+");
	if (!logfile) {
		printf("[%.3f] Error: unable to write log file\n", curtime());
	} else fclose(logfile);

	#ifndef DEDICATED_SERVER
		Console.consoleTempText = (char*)malloc(CONSOLE_TEMP_TEXT_SIZE); //FIXME
		Console.consoleTempTextPtr = Console.consoleTempText;
		Console.consoleTextSize = 16384;
	#endif

	logDisableDebugOutput = false;
}
Beispiel #12
0
// return capped length of time for the last cycle through main()'s loop
// (this value is used to tell the physics engine how much time to simulate.)
// also slow things down to MAXFPS; leave at least MINIDLEP% cpu idle
// TODO: avoid overflow with multi-second time deltas on 32 bit systems.
long timebal(void)
{
    long calctime, waitt, truewaitt, minidle, totalt;
    static long waitdiff;
    struct timespec now;
    static struct timespec markt, marktbeforeidle;


    now = curtime();
    if (markt.tv_sec == 0 && markt.tv_nsec == 0)
        markt = marktbeforeidle = now;

    calctime = convtns(tdiff(now, markt));
    marktbeforeidle = now;

    waitt = MINFT - calctime - waitdiff;
    // free a minimum of MINIDLEP% cpu
    minidle = calctime * MINIDLEP / 100;
    waitt = (waitt < minidle) ? minidle : waitt;

    waitns(waitt);
    markt = curtime();

    truewaitt = convtns(tdiff(markt, marktbeforeidle));
    if (waitdiff == 0)
        waitdiff = truewaitt - waitt;
    else
        waitdiff = (9 * waitdiff) / 10 + (truewaitt - waitt) / 10;

    totalt = calctime + truewaitt;
    // avoid positive feedback loop causing scheduled simulation time to
    // escalate on slower machines
    totalt = (totalt > MAXFT) ? MAXFT : totalt;

    return totalt;
}
int simulated_annealing(int n, double seconds) {
  default_random_engine rng;
  uniform_real_distribution<double> randfloat(0.0, 1.0);
  uniform_int_distribution<int> randint(0, n - 2);
  // random initial solution
  vi sol(n);
  rep(i,0,n) sol[i] = i + 1;
  random_shuffle(sol.begin(), sol.end());
  // initialize score
  int score = 0;
  rep(i,1,n) score += abs(sol[i] - sol[i-1]);
  int iters = 0;
  double T0 = 100.0, T1 = 0.001,
      progress = 0, temp = T0,
      starttime = curtime();
  while (true) {
    if (!(iters & ((1 << 4) - 1))) {
      progress = (curtime() - starttime) / seconds;
      temp = T0 * pow(T1 / T0, progress);
      if (progress > 1.0) break; }
    // random mutation
    int a = randint(rng);
    // compute delta for mutation
    int delta = 0;
    if (a > 0) delta += abs(sol[a+1] - sol[a-1])
                      - abs(sol[a] - sol[a-1]);
    if (a+2 < n) delta += abs(sol[a] - sol[a+2])
                        - abs(sol[a+1] - sol[a+2]);
    // maybe apply mutation
    if (delta >= 0 || randfloat(rng) < exp(delta / temp)) {
      swap(sol[a], sol[a+1]);
      score += delta;
      // if (score >= target) return;
    }
    iters++; }
  return score; }
Beispiel #14
0
void Network_Message::End() {
	if (!Network.msgSendLock) {
		logError("Trying to end message without starting it!");
	}
	*(unsigned short*)(rawBuffer) = rawSize; //Message size
	Network.numPacketsSent++;
	
	float fakeLag = Convar.GetFloat(Network.cvFakeLag)/1000.0f;
	if (fakeLag > 0.0f) {
		sendTime = curtime() + fakeLag;
	} else {
		doSendData();
		sendTime = 0.0f;
	}
	Thread.LeaveLock(Network.msgSendLock);
	Network.msgSendLock = 0;
}
Beispiel #15
0
static void pst(FILE *f) {
  double ct = curtime();
  double r[4] = { 0, 0, 0, 0 };
  unsigned c[4] = { 0, 0, 0, 0 };
  unsigned i;
  double d;
  for(i = 0; i < ntt; ++i) {
    d = ct - states[i].stime;
    r[states[i].opi] += states[i].ioc / d;
    c[states[i].opi] += states[i].ioc;
  }
//#if 1
//  for(i = 0; i < 4; ++i)
//    if (c[i])
//      fprintf(f, " %s %u %.2f", ion[i], c[i], r[i] * bs / 1024 / 1024);
//#endif
}
Beispiel #16
0
void dequeue(queue_t *q)
{
  int r;
  packet_t *pl;

  if (!lock(&q->lock)) return;

  pl = q->packetlist;
  while (pl) {
    if (q->mode & MODE_STREAM || pl->tstamp <= curtime()) {
      if (0 < (r = sendbuf(pl->p, pl->size, pl->frame == A ? AUDIO : VIDEO))) {
        q->bytes_sent += r;
        pl = delpacket(q, pl);
      }
    }
  }

  unlock(&q->lock);
}
Beispiel #17
0
void Network_Manager::Frame() {
	//Send delayed packets
		LockID lockID = Thread.EnterLock(MUTEX_NETWORK_SENDBUF);
		for (uint i = 0; i < Connections.Count; i++) {
			if (Connections[i]->connectionOpen) {
				for (uint j = 0; j < Connections[i]->sendQueue.AllocCount; j++) {
					if ((Connections[i]->sendQueue[j]->networkConnection) &&
						(Connections[i]->sendQueue[j]->sendTime > 0.0f) &&
						(curtime() > Connections[i]->sendQueue[j]->sendTime)) {
						Connections[i]->sendQueue[j]->doSendData();
					}
				}
			}
		}
	Thread.LeaveLock(lockID);

	//Update all connections
	for (uint i = 0; i < Connections.Count; i++) {
		if ((Connections[i]->socketHandle < 0) && (Connections[i]->connectionOpen)) {
			//Free up resources
			Connections[i]->Close();
			if (i == 0) {
					IsConnected = false;
					IsServer = false;
			}

			//Destroy client connections
			for (uint j = 0; j < Clients.List.AllocCount; j++) {
				if (Clients[j]->Connection == Connections[i]) {
					Clients[j]->Connection = 0;
				}
			}
		} else Connections[i]->Update();
	}

	//Check if we disconnected
	if (!IsServer) {
		if (Connections[0]->socketHandle < 0) IsConnected = false;
	}

	//Synchronize server time/get ping
	if ((!IsServer) && (IsConnected) && (curtime() - prevTimeSyncTick > (Convar.GetFloat(cvTimeRate)))) {
		prevTimeSyncTick = curtime();
		if (prevTimeSyncMessageTime <= 0) { //Make a new network request to server
			Network_Message* msg = Connections[0]->NewMessage();

			msg->Start(NETMESSAGE_TIMESYNC);
				msg->SendFloat(ServerTimer.Time());
			msg->End();

			prevTimeSyncMessageTime = ServerTimer.Time();
		}
	}

	/*if (Connections[1]->socketHandle >= 0) {
		if (Timer.Time() - testTime > 0.25f) {
			testTime = Timer.Time();
			char buf[256];
			sprintf(buf,"Time: %.3f\r",Timer.Time());

			Network_Message* msg = Connections[1]->NewMessage();
			msg->Start(100);
				msg->SendString(buf);
			msg->End();
		}
	}*/
}
Beispiel #18
0
Datei: clock.c Projekt: hvds/seq
void setup_clock(void) {
	clk_tck = sysconf(_SC_CLK_TCK);
	gtime = curtime();
}
Beispiel #19
0
Datei: clock.c Projekt: hvds/seq
void reset_clock(void) {
	gtime = curtime();
}
Beispiel #20
0
s64 curtime_ms()
{
	return(curtime()*1000);
}
Beispiel #21
0
double sendrate(queue_t *q) { return q->bytes_sent / curtime(); }
Beispiel #22
0
// main AI thinking routine, called every frame for every monster
void monsteraction(dynent *m) {
  if (m->enemy->state==CS_DEAD) {
    m->enemy = player1;
    m->anger = 0;
  }
  normalise(m, m->targetyaw);
  if (m->targetyaw>m->ypr.x) { // slowly turn monster towards his target
    m->ypr.x += curtime()*0.5f;
    if (m->targetyaw<m->ypr.x) m->ypr.x = m->targetyaw;
  } else {
    m->ypr.x -= curtime()*0.5f;
    if (m->targetyaw>m->ypr.x) m->ypr.x = m->targetyaw;
  }

  const float disttoenemy = distance(m->o, m->enemy->o);
  m->ypr.y = atan2(m->enemy->o.y-m->o.y, disttoenemy)*180.f/float(pi);

  // special case: if we run into scenery
  if (m->blocked) {
    m->blocked = false;
    // try to jump over obstackle (rare)
    if (!rnd(20000/monstertypes[m->mtype].speed))
      m->jumpnext = true;
    // search for a way around (common)
    else if (m->trigger<lastmillis() && (m->monsterstate!=M_HOME || !rnd(5))) {
      m->targetyaw += 180.f+rnd(180); // patented "random walk" AI pathfinding (tm) ;)
      transition(m, M_SEARCH, 1, 400, 1000);
    }
  }

  const auto enemyyaw = -atan2(m->enemy->o.x-m->o.x, m->enemy->o.z-m->o.z)/float(pi)*180.f+180.f;

  switch (m->monsterstate) {
    case M_PAIN:
    case M_ATTACKING:
    case M_SEARCH:
      if (m->trigger<lastmillis()) transition(m, M_HOME, 1, 100, 200);
    break;
    // state classic sp monster start in, wait for visual contact
    case M_SLEEP: {
      vec3f target;
      // skip running physics
      if (edit::mode() || !enemylos(m, target)) return;
      normalise(m, enemyyaw);
      const auto angle = abs(enemyyaw-m->ypr.x);
      if (disttoenemy<8.f ||  // the better the angle to the player
         (disttoenemy<16.f && angle<135.f) || // the further the monster can
         (disttoenemy<32.f && angle<90.f) ||  // see/hear
         (disttoenemy<64.f && angle<45.f) ||
         angle<10) {
        transition(m, M_HOME, 1, 500, 200);
        sound::play(sound::GRUNT1+rnd(2), &m->o);
      }
    }
    break;

    // this state is the delay between wanting to shoot and actually firing
    case M_AIMING:
      if (m->trigger<lastmillis()) {
        m->lastaction = 0;
        m->attacking = true;
        shoot(m, m->attacktarget);
        transition(m, M_ATTACKING, 0, 600, 0);
      }
    break;

    // monster has visual contact, heads straight for player and may want to
    // shoot at any time
    case M_HOME:
      m->targetyaw = enemyyaw;
      if (m->trigger<lastmillis()) {
        vec3f target;
        // no visual contact anymore, let monster get as close as possible then
        // search for player
        if (!enemylos(m, target))
          transition(m, M_HOME, 1, 800, 500);
        else  { // the closer the monster is the more likely he wants to shoot
          if (!rnd((int)disttoenemy/3+1) && m->enemy->state==CS_ALIVE) { // get ready to fire
            m->attacktarget = target;
            transition(m, M_AIMING, 0, monstertypes[m->mtype].lag, 10);
          } else // track player some more
            transition(m, M_HOME, 1, monstertypes[m->mtype].rate, 0);
        }
      }
    break;
  }
  physics::moveplayer(m, 1, false); // use physics to move monster
}
Beispiel #23
0
/**
 * Handles network traffic.
 */
void network() {
	char buffer[1024];
	size_t size;
	struct sockaddr src_addr;
	socklen_t addrlen;

	FD_ZERO(&readset);
	FD_SET(sockfd,&readset);

	tv.tv_sec = 0;
	tv.tv_usec = 0;

	if(select(sockfd+1,&readset,NULL,NULL,&tv) > 0) {
		size = recvfrom(sockfd, buffer, 1024, 0, &src_addr, &addrlen);
		//printf(">> %s\n", buffer);
		if(strncmp(buffer,"omg ",4)==0) {
				char * data = buffer+4;
				switch(state) {
					case STATE_INIT:
						break;
					case STATE_REQUESTED:
						if(CMD("nak")) {
							int slot;
							sscanf(data, "nak %d", &slot);
							printf("Recived nak for slot %i\n", slot);
							++slot;
							if(slot < 4) 
								request_slot(slot);
							else {
								printf("No free slots, shutting down");
								exit(2);
							}
						}
						break;
					case STATE_PLAYING: 
						if(CMD("req")) {
							int slot;
							sscanf(data, "req %d", &slot);
							if(me != NULL && me->id == slot) {
								sprintf(buffer, "omg nak %d", slot);
								send_msg(buffer);
							} else { 
								sprintf(buffer, "omg hai %d %f %f %f", me->id, me->pos.x, me->pos.y, me->angle);
								send_msg(buffer);
							}
						} else if(CMD("mov")) {
							int id;
							sscanf(data, "mov %d", &id);
							Player * p = get_or_create_plajur(id);
							if(p != NULL) {
								sscanf(data, "mov %d %f %f %f %d %f %f %f",&id, &p->pos.x, &p->pos.y, &p->angle, (int*)&p->current_base_texture, &p->velocity.x, &p->velocity.y, &p->da);
							}
						} else if(CMD("hai")) {
							int id;
							sscanf(data, "hai %d", &id);
							Player * p = get_or_create_plajur(id);
							if(p != NULL) {
								sscanf(data, "hai %d %f %f %f",&id, &p->pos.x, &p->pos.y, &p->angle);
							}
						} else if(CMD("rot")) {
							int id;
							sscanf(data, "rot %d", &id);
							Player * p = get_or_create_plajur(id);
							if(p != NULL) {
								sscanf(data, "rot %d %f %f",&id, &p->angle, &p->da);
							}
						} else if(CMD("fir")) {
							int id;
							sscanf(data, "fir %d", &id);
							Player * p = get_or_create_plajur(id);
							if(id != me->id && id < NUM_PLAYERS) {
								p->fire = true;
							}
						} else if(CMD("nof")) {
							int id;
							sscanf(data, "nof %d", &id);
							Player * p = players[id];
							if(id != me->id && p!=NULL) {
								p->fire = false;
							}
						} else if(CMD("kil")) {
							int id;
							sscanf(data, "kil %d", &id);
							Player * p = players[id];
							if(p!=NULL) {
								p->dead = 1;
							}
						}
						break;
				}
		} else {
			buffer[size] = 0;
			fprintf(stderr,"Recieved invalid data: %s\n", buffer);
		}
	}

	//Check if the slot request has time out (aka succeded)
	if(request_sent_time+0.5 < curtime() && state == STATE_REQUESTED) {
		ready = true;
		me = create_player(myname, requested_slot);
		state = STATE_PLAYING;
	}
}
Beispiel #24
0
void debugTestMalloc() {
	logWrite("Testing memory allocation");
	float startTime;
	logDisableDebugOutput = true;

	void* ptrs[TEST_ALLOCATIONS_IN_CYCLE];
	for (int j = 0; j < TEST_ALLOCATION_CYCLES; j++) {
		logWrite("Memory alloc/free cycle %d, peak usage %d bytes",j,mem.malloc_max);
		startTime = curtime();

		for (int i = 0; i < TEST_ALLOCATIONS_IN_CYCLE; i++) {
			ptrs[i] = mem.alloc(TEST_ALLOCATION_CYCLE_SIZE);
			if (!ptrs[i]) {
				logError("Memory test failed: null block returned");
				return;
			}
		}

		for (int i = 0; i < TEST_ALLOCATIONS_IN_CYCLE; i++) mem.free(ptrs[i]);

		logWrite("Cycle time %.5f seconds",curtime() - startTime);
	}

	logWrite("Allocating large memory chunk (%d mb)",TEST_ALLOC_LARGE_CHUNK_MB);
	startTime = curtime();
	void* largePtr = mem.alloc(TEST_ALLOC_LARGE_CHUNK_MB*1024*1024);
	logWrite("Done, %.5f seconds",curtime() - startTime);
	if (!largePtr) {
		logError("Could not allocate large memory chunk");
	}

	logWrite("Filling with pattern...");
	startTime = curtime();
	for (int i = 0; i < TEST_ALLOC_LARGE_CHUNK_MB*1024*1024; i++) {
		((char*)largePtr)[i] = (i ^ 0xFF) & 0xFF;
	}
	logWrite("Done, %.5f seconds",curtime() - startTime);	
	mem.free(largePtr);


	logWrite("Testing string pool...");
	for (int i = 0; i < TEST_ALLOCATE_NUM_STRINGS; i++) {
		int strSize = Random.Int(1,TEST_ALLOCATE_MAX_STR_SIZE);
		char* strPtr = mem.alloc_string(strSize);
		if (mem.malloc_memory > 256*1024*1024) {
			logWrite("Too much memory used, terminating earlier with %d strings",i+1);
			break;
		}
		for (int j = 0; j < strSize; j++) strPtr[j] = (i ^ j) & 0xFF;
	}
	int stringpool_size = 0;
	int stringpool_used = 0;
	int stringpool_lost = 0;
	for (int i = 0; i <= mem.malloc_curstringpool; i++) { 
		stringpool_size += mem.malloc_stringpoolsz[i];
		stringpool_used += mem.malloc_curstringpoolsz[i];
		stringpool_lost += mem.malloc_stringpoolsz[i] - mem.malloc_curstringpoolsz[i];
		
		if ((mem.malloc_stringpoolsz[i] <= 0) || (mem.malloc_stringpoolsz[i] > 16384) ||
			(mem.malloc_curstringpoolsz[i] <= 0) || (mem.malloc_curstringpoolsz[i] > 16384)) {
			logError("Memory test failed: corrupted string pool block %d",i);
			return;
		}
	}

	logWrite("String pool usage: %d out of %d bytes (%.2f percent, lost %d bytes, %d entries used)",
			stringpool_used,stringpool_size,(100.0f*stringpool_used) / stringpool_size,stringpool_lost,mem.malloc_curstringpool+1);

	logWrite("Testing boundary overflow detection");
	char* testPtr = (char*)mem.alloc(512);
	testPtr[600] = 0x10;
	mem.free(testPtr);

	logWrite("Reinitializing memory (and console variables, they are in mem too)...");
	logWrite("You should see warning about memory leak");
	Convar.Deinitialize();
	Memory.Deinitialize();
	logDisableDebugOutput = false;
	Memory.Initialize();
	Convar.Initialize();

	logWrite("Memory allocation test passed!\n");
}