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(); }
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); }
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); }
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; }
/* 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)); } }
/*=========================================================================== 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() */
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); } }
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; }
/***************************************************************** * 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 ); } }
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); }
void put16s(u16int *p, int n) { while(n--) put16(*p++); }
void xor_ax_imm16(unsigned short imm16) { put8(0x66); put8(0x35); put16(imm16); }
void or_ax_imm16(unsigned short imm16) { put8(0x66); put8(0x0D); put16(imm16); }
void and_ax_imm16(unsigned short imm16) { put8(0x66); put8(0x25); put16(imm16); }