CMathODE *SpanNew()
{
	CMathODE *ode = ODENew(0, 1e-4, ODEF_HAS_MASSES | ODEF_PAUSED);

	ode->derive				= &MyDerivative;
	ode->drag_v2			= 0.002;
	ode->drag_v3			= 0.00001;
	ode->acceleration_limit	= 5e3;
	QueueInsert(ode, Fs->last_ode);

	return ode;
}

U0 SpanDel(CMathODE *ode)
{
	if (ode)
	{
		QueueRemove(ode);
		QueueDel(&ode->next_mass, TRUE);
		QueueDel(&ode->next_spring, TRUE);
		ODEDel(ode);
	}
}

#define M_SIZE (sizeof(MyMass)	 - offset(CMass.start))
#define S_SIZE (sizeof(MySpring) - offset(CSpring.start))

U8 *SpanSave(CMathODE *ode, I64 *_size=NULL)
{
	I64			 count;
	U8			*res, *ptr;
	MyMass		*tmpm;
	MySpring	*tmps;
	SpanHeader	 h;

	ODERenum(ode);
	h.version = SPAN_VERSION;
	if (ode->next_mass != &ode->next_mass)
		h.num_masses = ode->last_mass->num + 1;
	else
		h.num_masses = 0;
	if (ode->next_spring != &ode->next_spring)
		h.num_springs = ode->last_spring->num + 1;
	else
		h.num_springs = 0;

	count = sizeof(SpanHeader) + h.num_masses * M_SIZE + h.num_springs * S_SIZE;

	ptr = res = MAlloc(count);
	MemCopy(ptr, &h, sizeof(SpanHeader));
	ptr += sizeof(SpanHeader);

	tmpm = ode->next_mass;
	while (tmpm != &ode->next_mass)
	{
		MemCopy(ptr, &tmpm->start, M_SIZE);
		ptr += M_SIZE;
		tmpm = tmpm->next;
	}

	tmps = ode->next_spring;
	while (tmps != &ode->next_spring)
	{
		MemCopy(ptr, &tmps->start, S_SIZE);
		ptr += S_SIZE;
		tmps = tmps->next;
	}
	if (_size)
		*_size = count;

	return res;
}

Bool SpanWrite(CMathODE *ode)
{
	U8	*name, *buf;
	I64	 size;
	Bool res = FALSE, old_silent = Silent;

	DirMake("~/Span");
	Silent(old_silent);
	if (name = PopUpFileName("~/Span/Game.DATA"))
	{
		if (buf = SpanSave(ode, &size))
		{
			FileWrite(name, buf, size);
			Free(buf);
			res = TRUE;
		}
		Free(name);
	}

	return res;
}

U0 SpanLoad(CMathODE *ode, U8 *src)
{
	I64		   i;
	MyMass	  *tmpm;
	MySpring  *tmps;
	SpanHeader h;

	if (!src)
		return;

	MemCopy(&h, src, sizeof(SpanHeader));
	src += sizeof(SpanHeader);

	for (i = 0; i < h.num_masses; i++)
	{
		tmpm = CAlloc(sizeof(MyMass));
		MemCopy(&tmpm->start, src, M_SIZE);
		src += M_SIZE;
		QueueInsert(tmpm, ode->last_mass);
	}

	for (i = 0; i < h.num_springs; i++)
	{
		tmps = CAlloc(sizeof(MySpring));
		MemCopy(&tmps->start, src, S_SIZE);
		src += S_SIZE;
		QueueInsert(tmps, ode->last_spring);
		tmps->end1 = MassFindNum(ode, tmps->end1_num);
		tmps->end2 = MassFindNum(ode, tmps->end2_num);
	}
}

U8 *SpanRead()
{
	U8	*src = NULL, *name;
	Bool old_silent = Silent;

	DirMake("~/Span");
	Silent(old_silent);
	if (name = PopUpPickFile("~/Span"))
	{
		src = FileRead(name);
		Free(name);
	}

	return src;
}

