bool FileRecorder::start(const std::string &filename) {
	_oldPos = _manager.pos();
	_startPos = _oldPos;
	_file = fopen(filename.c_str(), "wb");
	_filename = filename;
	if(_file == 0) {
		return false;
	}
	fwrite("RIFF\0\0\0\0WAVEfmt ", 16, 1, _file);

	put32(16, _file);
	put16(1, _file);

	_nchan = 0;
	for(unsigned int i = 0; i < _manager.recordingDevices().size(); i++) {
		if(_manager.recordingDevices()[i].bound)
			_nchan++;
	}

	put16(_nchan, _file);
	put32(_manager.sampleRate(), _file);

	int blockalign = _nchan*((16+7)/8);
	put32(_manager.sampleRate()*blockalign, _file);
	put16(blockalign, _file);
	put16(16, _file);

	fwrite("data\0\0\0\0", 8, 1, _file);

	return true;
}
void StreamCopyPaste::PutBuffer::put32(CARD32 value) {
	if (transferRec.bytesWritten == transferRec.bufferSize) {
		logger.error("bytesWritten == bufferSize");
		ERROR();
	}
	CARD16 b1 = (CARD16)value;
	CARD16 b2 = (CARD16)(value >> 16);
	put16(b1);
	put16(b2);
}
void FileRecorder::advance() {
	if(!recording())
		return;

	int len = _manager.pos() - _oldPos;

	if(_bufsize < len) {
		delete[] _buf;
		_buf = new int16_t[_nchan*len];
		_bufsize = len;
	}

	int chani = 0;
	for(unsigned int i = 0; i < _manager.recordingDevices().size(); i++) {
		if(_manager.recordingDevices()[i].bound) {
			_manager.getData(i, _oldPos, len, _buf+chani*_bufsize);
			chani++;
		}
	}

	for(int i = 0; i < len; i++) {
		for(int j = 0; j < _nchan; j++)
			put16(_buf[i+j*_bufsize], _file);
	}

	_oldPos = _manager.pos();
}
Beispiel #4
0
	void DataPage::setRecordOffsetAt(size_type index, size_type offset)
	{
		RAISE_INTERNAL_ERROR_IF_ARG(index > getNumberOfRecords());
		RAISE_INTERNAL_ERROR_IF_ARG(offset > size());

		const size_type keyOffsetPosition = HEADER_DATA_END_OFFSET + (index * sizeof(uint16_t));
		const uint16_t sixteenBitOffset = static_cast<uint16_t>(offset);
		put16(keyOffsetPosition, sixteenBitOffset);
	}
Beispiel #5
0
void writeTGA( char *name, byte *pixels, int width, int height)
{
    TargaHeader             targa_header;
    FILE *fin;

    fin = fopen( name, "wb" );
    if (!fin) {
        Debug( "Coulnd't open file for writing" );
        return;
    }

    memset( &targa_header, 0, sizeof( TargaHeader ) );

    fputc( 0, fin ); //targa_header.id_length = 0;
    fputc( 0, fin ); //targa_header.colormap_type = 0;
    fputc( 2, fin ); //targa_header.image_type = 2;
    put16( 0, fin ); //targa_header.colormap_index = 0;
    put16( 0, fin ); //targa_header.colormap_length = 0;
    fputc( 0, fin );			   //targa_header.colormap_size = 0;
    put16( 0,fin ); //targa_header.x_origin = 0;
    put16( 0, fin ); //targa_header.y_origin = 0;
    put16( width, fin );
    put16( height,fin );
    fputc( 24, fin ); //targa_header.pixel_size = 24 ;
    fputc( 0, fin );  //targa_header.attributes = 0;

    for (int i = 0; i < width*height*3; i+= 3)
    {
        fputc( (int)pixels[i+2], fin );
        fputc( (int)pixels[i+1], fin );
        fputc( (int)pixels[i], fin );
    }

    fclose(fin);
}
Beispiel #6
0
bool doarp(uint8_t *p, size_t nbytes, const char *dev)
{
  (void)nbytes; (void)dev;
  uint16_t op = ntohs(get16(p+14+6));
  char fromaddr[INET_ADDRSTRLEN];
  char toaddr[INET_ADDRSTRLEN];
  // Skip 14 bytes of ethernet header
  inet_ntop(AF_INET, p+14+14, fromaddr, sizeof(fromaddr));
  inet_ntop(AF_INET, p+14+24, toaddr, sizeof(toaddr));
  // Assume ethernet and IPv4
  printf("proto=ARP op=%u src=%s dst=%s\n",
         op, fromaddr, toaddr);
  // Now construct the ARP response
  put16(p+14+6,htons(2)); // Operation
  uint8_t *mac = p+14+18;
  mac[0] = 0x02; mac[1] = 0x00;
  memcpy(mac+2,p+14+24,4); // Use expected IP as top 4 bytes of MAC
  memcpy(p,mac,6); // Copy to source (it will be swapped later).
  swap(p+14+8,p+14+18,10);
  return true;
}
Beispiel #7
0
/* Convert TCP header in host format into mbuf ready for transmission,
 * link in data (if any).
 *
 * If checksum field is zero, recompute it, otherwise take the value
 * in the host header.
 */
void
htontcp(
struct tcp *tcph,
struct mbuf **bpp,	/* Data in, packet out */
int32 ipsrc,		/* For computing header checksum */
int32 ipdest
){
	uint16 hdrlen;
	register uint8 *cp;

	if(bpp == NULL)
		return;
	hdrlen = TCPLEN;
	if(tcph->flags.mss)
		hdrlen += MSS_LENGTH;
	if(tcph->flags.tstamp)
		hdrlen += TSTAMP_LENGTH;
	if(tcph->flags.wscale)
		hdrlen += WSCALE_LENGTH;

	hdrlen = (hdrlen + 3) & 0xfc;	/* Round up to multiple of 4 */
	pushdown(bpp,NULL,hdrlen);
	cp = (*bpp)->data;
	memset(cp,0,hdrlen);
	cp = put16(cp,tcph->source);
	cp = put16(cp,tcph->dest);
	cp = put32(cp,tcph->seq);
	cp = put32(cp,tcph->ack);
	*cp++ = hdrlen << 2;	/* Offset field */
	*cp = 0;
	if(tcph->flags.congest)
		*cp |= 64;
	if(tcph->flags.urg)
		*cp |= 32;
	if(tcph->flags.ack)
		*cp |= 16;
	if(tcph->flags.psh)
		*cp |= 8;
	if(tcph->flags.rst)
		*cp |= 4;
	if(tcph->flags.syn)
		*cp |= 2;
	if(tcph->flags.fin)
		*cp |= 1;
	cp++;
	cp = put16(cp,tcph->wnd);
	cp = put16(cp,tcph->checksum);
	cp = put16(cp,tcph->up);

	/* Write options, if any */
	if(tcph->flags.mss){
		*cp++ = MSS_KIND;
		*cp++ = MSS_LENGTH;
		cp = put16(cp,tcph->mss);
	}
	if(tcph->flags.tstamp){
		*cp++ = TSTAMP_KIND;
		*cp++ = TSTAMP_LENGTH;
		cp = put32(cp,tcph->tsval);
		cp = put32(cp,tcph->tsecr);
	}
	if(tcph->flags.wscale){
		*cp++ = WSCALE_KIND;
		*cp++ = WSCALE_LENGTH;
		*cp++ = tcph->wsopt;
	}
	if(tcph->checksum == 0){
		/* Recompute header checksum */
		struct pseudo_header ph;

		ph.source = ipsrc;
		ph.dest = ipdest;
		ph.protocol = TCP_PTCL;
		ph.length = len_p(*bpp);
		put16(&(*bpp)->data[16],cksum(&ph,*bpp,ph.length));
	}
}
Beispiel #8
0
/*===========================================================================
FUNCTION LCP_OPTION()

DESCRIPTION
  This function will add the given option to the DSM item passed in.

DEPENDENCIES
  None

RETURN VALUE
  None

SIDE EFFECTS
  None
===========================================================================*/
static void lcp_option
(
  ppp_fsm_type    *fsm_ptr,
  void            *vp,
  dsm_item_type **item_head_ptr,
  uint8           opt_num
)
{
  ppp_type       *ppp_cb_ptr = ppp_cb_array + fsm_ptr->device;
  lcp_value_type *value_p = (lcp_value_type *)vp;
  dsm_item_type  *bp = *item_head_ptr;
  register uint8 *cp;
  int n_type   = fsm_n_option(fsm_ptr->pdc,opt_num);
  int opt_len  = option_length[n_type];
  register int used = opt_len - OPTION_HDR_LEN;
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

  /*-------------------------------------------------------------------------
    this only tests for the minimum option length
  -------------------------------------------------------------------------*/
  if ( bp->used + opt_len > bp->size )
  {
    return;
  }
  cp = bp->data_ptr + bp->used;
  *cp++ = opt_num;
  /*-------------------------------------------------------------------------
    Note this length will be modified at the bottom if the option is longer
    than indicated by the default values - as it is if CHAP is enabled.
  -------------------------------------------------------------------------*/
  *cp++ = opt_len;

  /*-------------------------------------------------------------------------
    Determine the option type
  -------------------------------------------------------------------------*/
  switch( opt_num )
  {
    case LCP_MRU: /* Max Receive Unit */
      put16(cp, value_p->mru);
      used -= 2;
      break;

    case LCP_ACCM: /* Async Char Control Mask */
      put32(cp, value_p->accm);
      used -= 4;
      break;

    case LCP_AP: /* Authentication Protocol */
      cp = put16(cp, value_p->authentication);
      used -= 2;
      if(value_p->authentication == PPP_CHAP_PROTOCOL)
      {
        ppp_cb_ptr->auth.mode = PPP_DO_CHAP;

        /*-------------------------------------------------------------------
          Copy the CHAP digest. The digest algorithm number is appended after
          the CHAP protocol.
        -------------------------------------------------------------------*/
        *cp++ = value_p->chap_digest;
        used--;
      }
      else
      {
        ppp_cb_ptr->auth.mode = PPP_DO_PAP;
      }
      MSG_MED(" Make PPP cfg-nak: ask PAP/CHAP authen.",0,0,0);
      break;

    case LCP_MAGIC: /* Magic Number */
      put32(cp, value_p->magic_number);
      used -= 4;
      break;

    case LCP_PFC: /* Proto Field Compression */
      break;

    case LCP_ACFC: /* Address & Control Field Compression */
      break;
  };

  opt_len                    -= used;
  bp->data_ptr[bp->used + 1]  = opt_len;       /* length may be modified */
  bp->used                   += opt_len;

} /* lcp_option() */
Beispiel #9
0
static void
transmit(Wifi *wifi, Wnode *wn, Block *b)
{
	uchar c[Tcmdsize], *p;
	Ether *edev;
	Ctlr *ctlr;
	Wifipkt *w;
	int flags, nodeid, rate, timeout;
	char *err;

	edev = wifi->ether;
	ctlr = edev->ctlr;

	qlock(ctlr);
	if(ctlr->attached == 0 || ctlr->broken){
		qunlock(ctlr);
		freeb(b);
		return;
	}

	if((wn->channel != ctlr->channel)
	   || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
		rxon(edev, wn);

	if(b == nil){
		/* association note has no data to transmit */
		qunlock(ctlr);
		return;
	}

	flags = 0;
	timeout = 3;
	nodeid = ctlr->bcastnodeid;
	p = wn->minrate;
	w = (Wifipkt*)b->rp;
	if((w->a1[0] & 1) == 0){
		flags |= TFlagNeedACK;

		if(BLEN(b) > 512-4)
			flags |= TFlagNeedRTS|TFlagFullTxOp;

		if((w->fc[0] & 0x0c) == 0x08 &&	ctlr->bssnodeid != -1){
			timeout = 0;
			nodeid = ctlr->bssnodeid;
			p = wn->maxrate;
		}
	}
	qunlock(ctlr);

	rate = 0;
	if(p >= wpirates && p < &wpirates[nelem(ratetab)])
		rate = p - wpirates;

	memset(p = c, 0, sizeof(c));
	put16(p, BLEN(b)), p += 2;
	put16(p, 0), p += 2;	/* lnext */
	put32(p, flags), p += 4;
	*p++ = ratetab[rate].plcp;
	*p++ = nodeid;
	*p++ = 0;	/* tid */
	*p++ = 0;	/* security */
	p += 16+8;	/* key/iv */
	put32(p, 0), p += 4;	/* fnext */
	put32(p, 0xffffffff), p += 4;	/* livetime infinite */
	*p++ = 0xff;
	*p++ = 0x0f;
	*p++ = 7;
	*p++ = 15;
	put16(p, timeout), p += 2;
	put16(p, 0), p += 2;	/* txop */

	if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){
		print("transmit: %s\n", err);
		freeb(b);
	}
}
Beispiel #10
0
static void
rxon(Ether *edev, Wnode *bss)
{
	uchar c[Tcmdsize], *p;
	int filter, flags, rate;
	Ctlr *ctlr;
	char *err;
	int idx;

	ctlr = edev->ctlr;
	filter = FilterNoDecrypt | FilterMulticast;
	if(ctlr->prom){
		filter |= FilterPromisc;
		if(bss != nil)
			ctlr->channel = bss->channel;
		bss = nil;
	}
	if(bss != nil){
		ctlr->channel = bss->channel;
		memmove(ctlr->bssid, bss->bssid, Eaddrlen);
		ctlr->aid = bss->aid;
		if(ctlr->aid != 0){
			filter |= FilterBSS;
			ctlr->bssnodeid = -1;
		}else
			ctlr->bcastnodeid = -1;
	}else{
		memmove(ctlr->bssid, edev->bcast, Eaddrlen);
		ctlr->aid = 0;
		ctlr->bcastnodeid = -1;
		ctlr->bssnodeid = -1;
	}
	flags = RFlagTSF | RFlag24Ghz | RFlagAuto;

	if(ctlr->aid != 0)
		setled(ctlr, 2, 0, 1);		/* on when associated */
	else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
		setled(ctlr, 2, 10, 10);	/* slow blink when connecting */
	else
		setled(ctlr, 2, 5, 5);		/* fast blink when scanning */

	memset(p = c, 0, sizeof(c));
	memmove(p, edev->ea, 6); p += 8;	/* myaddr */
	memmove(p, ctlr->bssid, 6); p += 16;	/* bssid */
	*p++ = 3;				/* mode (STA) */
	p += 3;
	*p++ = 0xff;				/* ofdm mask (not yet negotiated) */
	*p++ = 0x0f;				/* cck mask (not yet negotiated) */
	put16(p, ctlr->aid & 0x3fff);		/* associd */
	p += 2;
	put32(p, flags);
	p += 4;
	put32(p, filter);
	p += 4;
	*p++ = ctlr->channel;
	p += 3;

	if((err = cmd(ctlr, 16, c, p - c)) != nil){
		print("rxon: %s\n", err);
		return;
	}

	/* tx power */
	memset(p = c, 0, sizeof(c));
	*p++ = 1;	/* band (0 = 5ghz) */
	p++;		/* reserved */
	put16(p, ctlr->channel), p += 2;
	for(rate = 0; rate < nelem(ratetab); rate++){
		idx = pwridx(ctlr, &ctlr->eeprom.pwrgrps[0], ctlr->channel, rate);
		*p++ = ratetab[rate].plcp;
		*p++ = rfgain_2ghz[idx];	/* rf_gain */
		*p++ = dspgain_2ghz[idx];	/* dsp_gain */
		p++;		/* reservd */
	}
	cmd(ctlr, 151, c, p - c);

	if(ctlr->bcastnodeid == -1){
		ctlr->bcastnodeid = 24;
		addnode(ctlr, ctlr->bcastnodeid, edev->bcast, ratetab[0].plcp, 3<<6);
	}
	if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
		ctlr->bssnodeid = 0;
		addnode(ctlr, ctlr->bssnodeid, bss->bssid, ratetab[0].plcp, 3<<6);
	}
}
int ExportQuake3Model(const TCHAR *filename, ExpInterface *ei, Interface *gi, int start_time, std::list<ExportNode> lTags, std::list<ExportNode> lMeshes)
{
	FILE *file;
	int i, j, totalTags, totalMeshes, current_time = 0;
	long pos_current, totalTris = 0, totalVerts = 0;
	std::list<FrameRange>::iterator range_i;
	std::vector<Point3> lFrameBBoxMin;
	std::vector<Point3> lFrameBBoxMax;
	long pos_tagstart;
	long pos_tagend;
	long pos_filesize;
	long pos_framestart;
	int lazynamesfixed = 0;
	const Point3 x_axis(1, 0, 0);
	const Point3 z_axis(0, 0, 1);

	SceneEnumProc checkScene(ei->theScene, start_time, gi);
	totalTags = (int)lTags.size();
	if (g_tag_for_pivot)
		totalTags++;
	totalMeshes = (int)lMeshes.size();

	// open file
	file = _tfopen(filename, _T("wb"));
	if (!file)
	{
		ExportError("Cannot open file '%s'.", filename);
		return FALSE;
	}
	ExportDebug("%s:", filename);

	// sync pattern and version
	putChars("IDP3", 4, file);
	put32(15, file);
	putChars("Darkplaces MD3 Exporter", 64, file);
	put32(0, file);   // flags
	
	// MD3 header
	ExportState("Writing MD3 header");
	put32(g_total_frames, file);      // how many frames
	put32(totalTags, file);	  // tagsnum
	put32(totalMeshes, file); // meshnum
	put32(1, file);   // maxskinnum
	put32(108, file); // headersize
	pos_tagstart = ftell(file); put32(0, file);   // tagstart
	pos_tagend	= ftell(file);  put32(256, file); // tagend
	pos_filesize = ftell(file); put32(512, file); // filesize
	ExportDebug("    %i frames, %i tags, %i meshes", g_total_frames, totalTags, totalMeshes);

	// frame info
	// bbox arrays get filled while exported mesh and written back then
	ExportState("Writing frame info");
	pos_framestart = ftell(file);
	lFrameBBoxMin.resize(g_total_frames);
	lFrameBBoxMax.resize(g_total_frames);
	for (i = 0; i < g_total_frames; i++)
	{
		// init frame data
		lFrameBBoxMin[i].Set(0, 0, 0);
		lFrameBBoxMax[i].Set(0, 0, 0);
		// put data
		putFloat(-1.0f, file); // bbox min vector
		putFloat(-1.0f, file);
		putFloat(-1.0f, file);	
		putFloat( 1.0f, file); // bbox max vector
		putFloat(1.0f, file);
		putFloat(1.0f, file);
		putFloat(0.0f, file);  // local origin (usually 0 0 0)
		putFloat(0.0f, file);
		putFloat(0.0f, file);
		putFloat(1.0f, file);  // radius of bounding sphere
		putChars("", 16, file);
	}

	// tags
	pos_current = ftell(file);
	fseek(file, pos_tagstart, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);
	
	// for each frame range cycle all frames and write out each tag
	long pos_tags = pos_current;
	if (totalTags)
	{
		long current_frame = 0;
		ExportState("Writing %i tags", totalTags);
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				SceneEnumProc current_scene(ei->theScene, i * g_ticks_per_frame, gi);
				current_time = current_scene.time;

				// write out tags
				if (lTags.size())
				{
					for (std::list<ExportNode>::iterator tag_i = lTags.begin(); tag_i != lTags.end(); tag_i++)
					{
						INode *node	= current_scene[tag_i->i]->node;
						Matrix3	tm = node->GetObjTMAfterWSM(current_time);

						ExportState("Writing '%s' frame %i of %i", tag_i->name, i, g_total_frames);

						// tagname
						putChars(tag_i->name, 64, file);
						// origin, rotation matrix
						Point3 row = tm.GetRow(3);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(0);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(1);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(2);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
					}
				}

				// write the center of mass tag_pivot which is avg of all objects's pivots
				if (g_tag_for_pivot)
				{
					ExportState("Writing 'tag_pivot' frame %i of %i", i, g_total_frames);

					// write the null data as tag_pivot need to be written after actual geometry
					// (it needs information on frame bound boxes to get proper blendings)
					putChars("tag_pivot", 64, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
				}
			}
		}
	}

	// write the tag object offsets
	pos_current = ftell(file);
	fseek(file, pos_tagend, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);

	// allocate the structs used to calculate tag_pivot
	std::vector<Point3> tag_pivot_origin;
	std::vector<double> tag_pivot_volume;
	if (g_tag_for_pivot)
	{
		tag_pivot_origin.resize(g_total_frames);
		tag_pivot_volume.resize(g_total_frames);
	}

	// mesh objects
	// for each mesh object write uv and frames
	SceneEnumProc scratch(ei->theScene, start_time, gi);
	ExportState("Writing %i meshes", (int)lMeshes.size());
	for (std::list<ExportNode>::iterator mesh_i = lMeshes.begin(); mesh_i != lMeshes.end(); mesh_i++)
	{
		bool needsDel;

		ExportState("Start mesh #%i", mesh_i);
		INode *node = checkScene[mesh_i->i]->node;
		Matrix3 tm	= node->GetObjTMAfterWSM(start_time);
		TriObject *tri = GetTriObjectFromNode(node, start_time, needsDel);
		if (!tri)
			continue;

		// get mesh, compute normals
		Mesh &mesh = tri->GetMesh();
		MeshNormalSpec *meshNormalSpec = mesh.GetSpecifiedNormals();
		if (meshNormalSpec)
		{
			if (!meshNormalSpec->GetNumFaces())
				meshNormalSpec = NULL;
			else
			{
				meshNormalSpec->SetParent(&mesh);
				meshNormalSpec->CheckNormals();
			}
		}
		mesh.checkNormals(TRUE);

		// fix lazy object names
		ExportState("Attempt to fix mesh name '%s'", mesh_i->name);
		char  meshname[64];
		size_t meshnamelen = min(63, strlen(mesh_i->name));
		memset(meshname, 0, 64);
		strncpy(meshname, mesh_i->name, meshnamelen);
		meshname[meshnamelen] = 0;
		if (!strncmp("Box", meshname, 3)    || !strncmp("Sphere", meshname, 6)  || !strncmp("Cylinder", meshname, 8) ||
            !strncmp("Torus", meshname, 5)  || !strncmp("Cone", meshname, 4)    || !strncmp("GeoSphere", meshname, 9) ||
			!strncmp("Tube", meshname, 4)   || !strncmp("Pyramid", meshname, 7) || !strncmp("Plane", meshname, 5) ||
			!strncmp("Teapot", meshname, 6) || !strncmp("Object", meshname, 6))
		{
name_conflict:
			lazynamesfixed++;
			if (lazynamesfixed == 1)
				strcpy(meshname, "base");
			else
				sprintf(meshname, "base%i", lazynamesfixed);

			// check if it's not used by another mesh
			for (std::list<ExportNode>::iterator m_i = lMeshes.begin(); m_i != lMeshes.end(); m_i++)
				if (!strncmp(m_i->name, meshname, strlen(meshname)))
					goto name_conflict;
			// approve name
			ExportWarning("Lazy object name '%s' (mesh renamed to '%s').", node->GetName(), meshname);
		}

		// special mesh check
		bool shadow_or_collision = false;
		if (g_mesh_special)
			  if (!strncmp("collision", meshname, 9) || !strncmp("shadow", meshname, 6))
				shadow_or_collision = true;

		// get material
		const char *shadername = NULL;
		Texmap *tex = 0;
		Mtl *mtl = 0;
		if (!shadow_or_collision)
		{
			mtl = node->GetMtl();
			if (mtl)
			{
				// check for multi-material
				if (mtl->IsMultiMtl())
				{
					// check if it's truly multi material
					// we do support multi-material with only one texture (some importers set it)
					bool multi_material = false;
					MtlID matId = mesh.faces[0].getMatID();
					for (i = 1; i < mesh.getNumFaces(); i++)
						if (mesh.faces[i].getMatID() != matId)
							multi_material = true;

					if (multi_material)
						if (g_mesh_multimaterials == MULTIMATERIALS_NONE)
							ExportWarning("Object '%s' is multimaterial and using multiple materials on its faces, that case is not yet supported (truncating to first submaterial).", node->GetName());
					
					// switch to submaterial
					mtl = mtl->GetSubMtl(matId);
				}

				// get shader from material if supplied
				char *materialname = GetChar(mtl->GetName());
				if (g_mesh_materialasshader && (strstr(materialname, "/") != NULL || strstr(materialname, "\\") != NULL))
					shadername = GetChar(mtl->GetName());
				else
				{
					// get texture
					tex = mtl->GetSubTexmap(ID_DI);
					if (tex)
					{
						if (tex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00))
						{
							shadername = GetChar(((BitmapTex *)tex)->GetMapName());
							if (shadername == NULL || !shadername[0])
								ExportWarning("Object '%s' material '%s' has no bitmap.", tex->GetName(), node->GetName());
						}
						else
						{
							tex = NULL;
							ExportWarning("Object '%s' has material with wrong texture type (only Bitmap are supported).", node->GetName());
						}
					}
					else
						ExportWarning("Object '%s' has material but no texture.", node->GetName());
				}
			}
			else
				ExportWarning("Object '%s' has no material.", node->GetName());
		}

		long pos_meshstart = ftell(file);

		// surface object
		ExportState("Writing mesh '%s' header", meshname);
		putChars("IDP3", 4, file);
		putChars(meshname, 64, file);
		put32(0, file); // flags
		put32(g_total_frames, file);                          // framecount
		put32(1, file);                                       // skincount
		long pos_vertexnum = ftell(file); put32(0, file);     // vertexcount
		put32(mesh.getNumFaces(), file);                      // trianglecount
		long pos_trianglestart = ftell(file); put32(0, file); // start triangles
		put32(108, file);                                     // header size
		long pos_texvecstart = ftell(file); put32(0, file);   // texvecstart
		long pos_vertexstart = ftell(file); put32(16, file);  // vertexstart
		long pos_meshsize = ftell(file); put32(32, file);	  // meshsize

		// write out a single 'skin'
		ExportState("Writing mesh %s texture", meshname);
		if (shadow_or_collision)
			putChars(meshname, 64, file);
		else if (shadername) 
			putMaterial(shadername, mtl, tex, file);
		else
			putChars("noshader", 64, file);
		put32(0, file); // flags

		// build geometry
		ExportState("Building vertexes/triangles");
		std::vector<ExportVertex>vVertexes;
		std::vector<ExportTriangle>vTriangles;
		vVertexes.resize(mesh.getNumVerts());
		int vExtraVerts = mesh.getNumVerts();
		for (i = 0; i < mesh.getNumVerts(); i++)
		{
			vVertexes[i].vert = i;
			vVertexes[i].normalfilled = false;
			// todo: check for coincident verts
		}
		int vNumExtraVerts = 0;

		// check normals
		if (!mesh.normalsBuilt && !shadow_or_collision)
			ExportWarning("Object '%s' does not have normals contructed.", node->GetName());

		// get info for triangles
		const float normal_epsilon = 0.01f;
		vTriangles.resize(mesh.getNumFaces());
		for (i = 0; i < mesh.getNumFaces(); i++)
		{
			DWORD smGroup = mesh.faces[i].getSmGroup();
			ExportState("Mesh %s: checking normals for face %i of %i", meshname, i, mesh.getNumFaces());
			for (j = 0; j < 3; j++)
			{
				int vert = mesh.faces[i].getVert(j);
				vTriangles[i].e[j] = vert;
				// find a right normal for this vertex and save its 'address'
				int vni;
				Point3 vn;
				if (!mesh.normalsBuilt || shadow_or_collision)
				{
					vn.Set(0, 0, 0);
					vni = 0;
				}
				else
				{
					int numNormals;
					RVertex *rv = mesh.getRVertPtr(vert);
					if (meshNormalSpec)
					{  
						ExportState("face %i vert %i have normal specified", i, j);
						// mesh have explicit normals (i.e. Edit Normals modifier)
						vn = meshNormalSpec->GetNormal(i, j);
						vni = meshNormalSpec->GetNormalIndex(i, j);
					}
					else if (rv && rv->rFlags & SPECIFIED_NORMAL)
					{
						ExportState("face %i vert %i have SPECIFIED_NORMAL flag", i, j);
						// SPECIFIED_NORMAL flag
						vn = rv->rn.getNormal();
						vni = 0;
					}
					else if (rv && (numNormals = rv->rFlags & NORCT_MASK) && smGroup)
					{
						// If there is only one vertex is found in the rn member.
						if (numNormals == 1)
						{
							ExportState("face %i vert %i have solid smooth group", i, j);
							vn = rv->rn.getNormal();
							vni = 0;
							
						}
						else
						{
							ExportState("face %i vert %i have mixed smoothing groups", i, j);
							// If two or more vertices are there you need to step through them
							// and find the vertex with the same smoothing group as the current face.
							// You will find multiple normals in the ern member.
							for (int k = 0; k < numNormals; k++)
							{
								if (rv->ern[k].getSmGroup() & smGroup)
								{
									vn = rv->ern[k].getNormal();
									vni = 1 + k;
								}
							}
						}
					}
					else
					{
						ExportState("face %i vert %i flat shaded", i, j);
						// Get the normal from the Face if no smoothing groups are there
						vn = mesh.getFaceNormal(i);
						vni = 0 - (i + 1);
					}
				}

				// subdivide to get all normals right
				if (!vVertexes[vert].normalfilled)
				{
					vVertexes[vert].normal = vn;
					vVertexes[vert].normalindex = vni;
					vVertexes[vert].normalfilled = true;
				}
				else if ((vVertexes[vert].normal - vn).Length() >= normal_epsilon)
				{
					// current vertex not matching normal - it was already filled by different smoothing group
					// find a vert in extra verts in case it was already created
					bool vert_found = false;
					for (int ev = vExtraVerts; ev < (int)vVertexes.size(); ev++)
					{
						if (vVertexes[ev].vert == vert && (vVertexes[ev].normal - vn).Length() < normal_epsilon)
						{
							vert_found = true;
							vTriangles[i].e[j] = ev;
							break;
						}
					}
					// we havent found a vertex, create new
					if (!vert_found)
					{
						ExportVertex NewVert;
						NewVert.vert = vVertexes[vert].vert;
						NewVert.normal = vn;
						NewVert.normalindex = vni;
						NewVert.normalfilled = true;
						vTriangles[i].e[j] = (int)vVertexes.size();
						vVertexes.push_back(NewVert);
						vNumExtraVerts++;
					}
				}
			}
		}
		int vNumExtraVertsForSmoothGroups = vNumExtraVerts;

		// generate UV map
		// VorteX: use direct maps reading since getNumTVerts()/getTVert is deprecated
		//  max sets two default mesh maps: 0 - vertex color, 1 : UVW, 2 & up are custom ones
		ExportState("Building UV map");
		std::vector<ExportUV>vUVMap;
		vUVMap.resize(vVertexes.size());
		int meshMap = 1;
		if (!mesh.mapSupport(meshMap) || !mesh.getNumMapVerts(meshMap) || shadow_or_collision)
		{
			for (i = 0; i < mesh.getNumVerts(); i++)
			{
				vUVMap[i].u = 0.5;
				vUVMap[i].v = 0.5;
			}
			if (!shadow_or_collision)
				ExportWarning("No UV mapping was found on object '%s'.", node->GetName());
		}
		else
		{
			UVVert *meshUV = mesh.mapVerts(meshMap);
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				ExportState("Mesh %s: converting tvert for face %i of %i", meshname, i, (int)vTriangles.size());
				// for 3 face vertexes
				for (j = 0; j < 3; j++)
				{
					int vert = vTriangles[i].e[j];
					int tv = mesh.tvFace[i].t[j];
					UVVert &UV = meshUV[tv];

					if (!vUVMap[vert].filled)
					{
						// fill uvMap vertex
						vUVMap[vert].u = UV.x;
						vUVMap[vert].v = UV.y;
						vUVMap[vert].filled = true;
						vUVMap[vert].tvert = tv;
					}
					else if (tv != vUVMap[vert].tvert)
					{
						// uvMap slot for this vertex has been filled
						// we should arrange triangle to other vertex, which not filled and having same shading and uv
						// check if any of the extra vertices can fit
						bool vert_found = false;
						for (int ev = vExtraVerts; ev < (int)vVertexes.size(); ev++)
						{
							if (vVertexes[ev].vert == vert && vUVMap[vert].u == UV.x &&vUVMap[vert].v == UV.y  && (vVertexes[ev].normal - vVertexes[vert].normal).Length() < normal_epsilon)
							{
								vert_found = true;
								vTriangles[i].e[j] = vVertexes[ev].vert;
								break;
							}
						}
						if (!vert_found)
						{
							// create new vert
							ExportVertex NewVert;
							NewVert.vert = vVertexes[vert].vert;
							NewVert.normal = vVertexes[vert].normal;
							NewVert.normalindex = vVertexes[vert].normalindex;
							NewVert.normalfilled = vVertexes[vert].normalfilled;
							vTriangles[i].e[j] = (int)vVertexes.size();
							vVertexes.push_back(NewVert);
							vNumExtraVerts++;
							// create new TVert
							ExportUV newUV;
							newUV.filled = true;
							newUV.u = UV.x;
							newUV.v = UV.y;
							newUV.tvert = tv;
							vUVMap.push_back(newUV);
						}
					}
				}
			}
		}
		int vNumExtraVertsForUV = (vNumExtraVerts - vNumExtraVertsForSmoothGroups);

		// print some debug stats
		ExportDebug("    mesh %s: %i vertexes +%i %s +%i UV, %i triangles", meshname, ((int)vVertexes.size() - vNumExtraVerts), vNumExtraVertsForSmoothGroups, meshNormalSpec ? "EditNormals" : "SmoothGroups", vNumExtraVertsForUV, (int)vTriangles.size());

		// fill in triangle start
		pos_current = ftell(file);
		fseek(file, pos_trianglestart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);

		// detect if object have negative scale (mirrored)
		// in this canse we should rearrange triangles counterclockwise
		// so stuff will not be inverted
		ExportState("Mesh %s: writing %i triangles", meshname, (int)vTriangles.size());
		if (DotProd(CrossProd(tm.GetRow(0), tm.GetRow(1)), tm.GetRow(2)) < 0.0)
		{
			ExportWarning("Object '%s' is mirrored (having negative scale on it's transformation)", node->GetName());
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				put32(vTriangles[i].b, file);	// vertex index
				put32(vTriangles[i].c, file);	// for 3 vertices
				put32(vTriangles[i].a, file);	// of triangle
			}
		}
		else
		{
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				put32(vTriangles[i].a, file);	// vertex index
				put32(vTriangles[i].c, file);	// for 3 vertices
				put32(vTriangles[i].b, file);	// of triangle
			}
		}

		// fill in texvecstart
		// write out UV mapping coords.
		ExportState("Mesh %s: writing %i UV vertexes", meshname, (int)vUVMap.size());
		pos_current = ftell(file);
		fseek(file, pos_texvecstart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);
		for (i = 0; i < (int)vUVMap.size(); i++)
		{
			putFloat(vUVMap[i].u, file); // texture coord u,v
			putFloat(1.0f - vUVMap[i].v, file);	// for vertex
		}
		vUVMap.clear();

		// fill in vertexstart
		pos_current = ftell(file);
		fseek(file, pos_vertexstart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);

		// fill in vertexnum
		pos_current = ftell(file);
		fseek(file, pos_vertexnum, SEEK_SET);
		put32((int)vVertexes.size(), file);
		fseek(file, pos_current, SEEK_SET);

		// write out for each frame the position of each vertex
		long current_frame = 0;
		ExportState("Mesh %s: writing %i frames", meshname, g_total_frames);
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				bool _needsDel;

				// get triobject for current frame
				SceneEnumProc current_scene(ei->theScene, i * g_ticks_per_frame, gi);
				current_time = current_scene.time;
				INode *_node = current_scene[mesh_i->i]->node;
				TriObject *_tri	= GetTriObjectFromNode(_node, current_time, _needsDel);
				if (!_tri)
					continue;

				// get mesh, compute normals
				Mesh &_mesh	= _tri->GetMesh();
				MeshNormalSpec *_meshNormalSpec = _mesh.GetSpecifiedNormals();
				if (_meshNormalSpec)
				{
					if (!_meshNormalSpec->GetNumFaces())
						_meshNormalSpec = NULL;
					else
					{
						_meshNormalSpec->SetParent(&_mesh);
						_meshNormalSpec->CheckNormals();
					}
				}
				_mesh.checkNormals(TRUE);

				// get transformations for current frame
				Matrix3 _tm	= _node->GetObjTMAfterWSM(current_time);

				ExportState("Mesh %s: writing frame %i of %i", meshname, current_frame, g_total_frames);

				Point3 BoxMin(0, 0, 0);
				Point3 BoxMax(0, 0, 0);
				for (j = 0; j < (int)vVertexes.size(); j++) // number of vertices
				{
					ExportState("Mesh %s: transform vertex %i of %i", meshname, j, (int)vVertexes.size());

					int vert = vVertexes[j].vert;
					Point3 &v = _tm.PointTransform(_mesh.getVert(vert));
					
					// populate bbox data
					if (!shadow_or_collision)
					{
						BoxMin.x = min(BoxMin.x, v.x);
						BoxMin.y = min(BoxMin.y, v.y);
						BoxMin.z = min(BoxMin.z, v.z);
						BoxMax.x = max(BoxMax.x, v.x);
						BoxMax.y = max(BoxMax.y, v.y);
						BoxMax.z = max(BoxMax.z, v.z);
					}

					// write vertex
					double f;
					f = v.x * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);
					f = v.y * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);
					f = v.z * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);

					// get normal
					ExportState("Mesh %s: transform vertex normal %i of %i", meshname, j, (int)vVertexes.size());
					Point3 n;
					if (_meshNormalSpec) // mesh have explicit normals (i.e. Edit Normals modifier)
						n = _meshNormalSpec->Normal(vVertexes[j].normalindex);
					else if (!vVertexes[j].normalfilled || !_mesh.normalsBuilt)
						n = _mesh.getNormal(vert);
					else
					{
						RVertex *rv = _mesh.getRVertPtr(vert);
						if (vVertexes[j].normalindex < 0)
							n = _mesh.getFaceNormal((0 - vVertexes[j].normalindex) - 1);
						else if (vVertexes[j].normalindex == 0)
							n = rv->rn.getNormal();
						else 
							n = rv->ern[vVertexes[j].normalindex - 1].getNormal();
					}

					// transform normal
					Point3 &nt = _tm.VectorTransform(n).Normalize();

					// encode a normal vector into a 16-bit latitude-longitude value
					double lng = acos(nt.z) * 255 / (2 * pi);
					double lat = atan2(nt.y, nt.x) * 255 / (2 * pi);
					put16((((int)lat & 0xFF) << 8) | ((int)lng & 0xFF), file);
				}

				// blend the pivot positions for tag_pivot using mesh's volumes for blending power
				if (g_tag_for_pivot && !shadow_or_collision)
				{
					ExportState("Mesh %s: writing tag_pivot", meshname);

					Point3 Size = BoxMax - BoxMin;
					double BoxVolume = pow(Size.x * Size.y * Size.z, 0.333f);

					// blend matrices
					float blend = (float)(BoxVolume / (BoxVolume + tag_pivot_volume[current_frame]));
					float iblend = 1 - blend;
					tag_pivot_volume[current_frame]   = tag_pivot_volume[current_frame] + BoxVolume;
					Point3 row = _tm.GetRow(3) - _node->GetObjOffsetPos();
					tag_pivot_origin[current_frame].x = tag_pivot_origin[current_frame].x * iblend + row.x * blend;
					tag_pivot_origin[current_frame].y = tag_pivot_origin[current_frame].y * iblend + row.y * blend;
					tag_pivot_origin[current_frame].z = tag_pivot_origin[current_frame].z * iblend + row.z * blend;
				}

				// populate bbox data for frames
				lFrameBBoxMin[current_frame].x = min(lFrameBBoxMin[current_frame].x, BoxMin.x);
				lFrameBBoxMin[current_frame].y = min(lFrameBBoxMin[current_frame].y, BoxMin.y);
				lFrameBBoxMin[current_frame].z = min(lFrameBBoxMin[current_frame].z, BoxMin.z);
				lFrameBBoxMax[current_frame].x = max(lFrameBBoxMax[current_frame].x, BoxMax.x);
				lFrameBBoxMax[current_frame].y = max(lFrameBBoxMax[current_frame].y, BoxMax.y);
				lFrameBBoxMax[current_frame].z = max(lFrameBBoxMax[current_frame].z, BoxMax.z);

				// delete the working object, if necessary.
				if (_needsDel)
					delete _tri;
			}
		}

		// delete if necessary
		if (needsDel)
			delete tri;

		// fill in meshsize
		pos_current = ftell(file);
		fseek(file, pos_meshsize, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);  

		// reset back to first frame
		SceneEnumProc scratch(ei->theScene, start_time, gi);
		totalTris += (long)vTriangles.size();
		totalVerts += (long)vVertexes.size();
		vTriangles.clear();
		vVertexes.clear();
	}

	// write tag_pivot
	ExportState("Writing tag_pivot positions");
	if (g_tag_for_pivot)
	{
		pos_current = ftell(file);
		long current_frame = 0;
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				fseek(file, pos_tags + totalTags*112*current_frame + (int)lTags.size()*112 + 64, SEEK_SET);
				// origin
				putFloat(tag_pivot_origin[current_frame].x, file);
				putFloat(tag_pivot_origin[current_frame].y, file);
				putFloat(tag_pivot_origin[current_frame].z, file);
			}
		}
		fseek(file, pos_current, SEEK_SET);
	}
	tag_pivot_volume.clear();
	tag_pivot_origin.clear();

	// write frame data
	ExportState("Writing culling info");
	long current_frame = 0;
	pos_current = ftell(file);
	for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
	{
		for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
		{
			fseek(file, pos_framestart + current_frame*56, SEEK_SET);
			putFloat(lFrameBBoxMin[current_frame].x, file);	// bbox min vector
			putFloat(lFrameBBoxMin[current_frame].y, file);
			putFloat(lFrameBBoxMin[current_frame].z, file);	
			putFloat(lFrameBBoxMax[current_frame].x, file); // bbox max vector
			putFloat(lFrameBBoxMax[current_frame].y, file);
			putFloat(lFrameBBoxMax[current_frame].z, file);
			putFloat(0, file); // local origin (usually 0 0 0)
			putFloat(0, file);
			putFloat(0, file);
			putFloat(max(lFrameBBoxMin[current_frame].Length(), lFrameBBoxMax[current_frame].Length()) , file); // radius of bounding sphere
		}
	}
	fseek(file, pos_current, SEEK_SET);
	lFrameBBoxMin.clear();
	lFrameBBoxMax.clear();

	// fill in filesize
	pos_current = ftell(file);
	fseek(file, pos_filesize, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);

	fclose(file);

	ExportDebug("    total: %i vertexes, %i triangles", totalVerts, totalTris);

	return TRUE;
}
Beispiel #12
0
/*****************************************************************
 * TAG( RunSetup )
 * Put out initial setup data for RLE files.
 */
void
RunSetup(rle_hdr * the_hdr)
{
    struct XtndRsetup setup;
    register FILE * rle_fd = the_hdr->rle_file;

    put16( RLE_MAGIC );

    if ( the_hdr->background == 2 )
        setup.h_flags = H_CLEARFIRST;
    else if ( the_hdr->background == 0 )
        setup.h_flags = H_NO_BACKGROUND;
    else
        setup.h_flags = 0;
    if ( the_hdr->alpha )
        setup.h_flags |= H_ALPHA;
    if ( the_hdr->comments != NULL && *the_hdr->comments != NULL )
        setup.h_flags |= H_COMMENT;

    setup.h_ncolors = the_hdr->ncolors;
    setup.h_pixelbits = 8;		/* Grinnell dependent */
    if ( the_hdr->ncmap > 0 && the_hdr->cmap == NULL )
    {
        fprintf( stderr,
                 "%s: Color map of size %d*%d specified, but not supplied, writing %s\n",
                 the_hdr->cmd, the_hdr->ncmap, (1 << the_hdr->cmaplen),
                 the_hdr->file_name );
        the_hdr->ncmap = 0;
    }
    setup.h_cmaplen = the_hdr->cmaplen;	/* log2 of color map size */
    setup.h_ncmap = the_hdr->ncmap;	/* no of color channels */
    vax_pshort(setup.hc_xpos,the_hdr->xmin);
    vax_pshort(setup.hc_ypos,the_hdr->ymin);
    vax_pshort(setup.hc_xlen,the_hdr->xmax - the_hdr->xmin + 1);
    vax_pshort(setup.hc_ylen,the_hdr->ymax - the_hdr->ymin + 1);
    fwrite((char *)&setup, SETUPSIZE, 1, rle_fd);
    if ( the_hdr->background != 0 )
    {
        register int i;
        register rle_pixel *background =
            (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
        register int *bg_color;
        /*
         * If even number of bg color bytes, put out one more to get to
         * 16 bit boundary.
         */
        bg_color = the_hdr->bg_color;
        for ( i = 0; i < the_hdr->ncolors; i++ )
            background[i] =  *bg_color++;
        /* Extra byte, if written, should be 0. */
        background[i] = 0;
        fwrite((char *)background, (the_hdr->ncolors / 2) * 2 + 1, 1, rle_fd);
        free( background );
    }
    else
        putc( '\0', rle_fd );
    if (the_hdr->ncmap > 0)
    {
        /* Big-endian machines are harder */
        register int i, nmap = (1 << the_hdr->cmaplen) *
                               the_hdr->ncmap;
        register char *h_cmap = (char *)malloc( nmap * 2 );
        if ( h_cmap == NULL )
        {
            fprintf( stderr,
                     "%s: Malloc failed for color map of size %d, writing %s\n",
                     the_hdr->cmd, nmap, the_hdr->file_name );
            exit( 1 );
        }
        for ( i = 0; i < nmap; i++ )
            vax_pshort( &h_cmap[i*2], the_hdr->cmap[i] );

        fwrite( h_cmap, nmap, 2, rle_fd );
        free( h_cmap );
    }

    /* Now write out comments if given */
    if ( setup.h_flags & H_COMMENT )
    {
        int comlen;
        register CONST_DECL char ** com_p;

        /* Get the total length of comments */
        comlen = 0;
        for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
            comlen += 1 + strlen( *com_p );

        put16( comlen );
        for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
            fwrite( *com_p, 1, strlen( *com_p ) + 1, rle_fd );

        if ( comlen & 1 )	/* if odd length, round up */
            putc( '\0', rle_fd );
    }
}
Beispiel #13
0
void
savestate(char *file)
{
	flushram();
	bp = Bopen(file, OWRITE);
	if(bp == nil){
		message("open: %r");
		return;
	}
	Bwrite(bp, reg, sizeof(reg));
	Bwrite(bp, mem, sizeof(mem));
	Bwrite(bp, vram, sizeof(vram));
	Bwrite(bp, oam, sizeof(oam));
	Bwrite(bp, spcmem, sizeof(spcmem));
	Bwrite(bp, dsp, sizeof(dsp));
	put16s(cgram, nelem(cgram));
	put32(ppuclock);
	put32(spcclock);
	put32(dspclock);
	put32(stimerclock);
	put16(rA);
	put16(rX);
	put16(rY);
	put16(rS);
	put8(rP);
	put16(rD);
	put8(rDB>>16);
	put16(pc);
	put8(rPB>>16);
	put8(emu);
	put8(irq);
	put8(nmi);
	put8(dma);
	put32(hdma);
	put8(wai);
	put8(mdr);
	put8(mdr1);
	put8(mdr2);
	put16(oamaddr);
	put16(vramlatch);
	put32(keylatch);
	put16(ppux);
	put16(ppuy);
	put16(subcolor);
	put16s(hofs, nelem(hofs));
	put16s(vofs, nelem(vofs));
	put16s((u16int*) m7, nelem(m7));
	put8(sA);
	put8(sX);
	put8(sY);
	put8(sS);
	put8(sP);
	put8(dspstate);
	put16(dspcounter);
	put16(noise);
	Bwrite(bp, spctimer, sizeof(spctimer));
	dspsave();
	Bterm(bp);
}
Beispiel #14
0
void
put16s(u16int *p, int n)
{
	while(n--)
		put16(*p++);
}
Beispiel #15
0
void xor_ax_imm16(unsigned short imm16)
{
   put8(0x66);
   put8(0x35);
   put16(imm16);
}
Beispiel #16
0
void or_ax_imm16(unsigned short imm16)
{
   put8(0x66);
   put8(0x0D);
   put16(imm16);
}
Beispiel #17
0
void and_ax_imm16(unsigned short imm16)
{
   put8(0x66);
   put8(0x25);
   put16(imm16);
}