void render_lodder_sphere(int group, Vertex spherepos, Vertex spherepos2, float diam, float powr, float push, float timex) { Vertex *loddata[MAX_LOD_REDUCTION+1]; Vertex *v, *n; int vc=loddermesh->groups[group]->vc; int fc=loddermesh->groups[group]->fc; int *i=loddermesh->groups[group]->indices; float *c; unsigned char *lodlevels; // assign lod buffers, 0=original loddata[0]=loddermesh->groups[group]->vertices; for (int i=0; i<MAX_LOD_REDUCTION; i++) loddata[i+1]=lodder_vertices[group][i]; v=tmpmalloc(sizeof(Vertex)*vc); n=tmpmalloc(sizeof(Vertex)*vc); c=tmpmalloc(sizeof(float)*vc*4); lodlevels=tmpmalloc(vc); // calc vertices for (int x=0; x<vc; x++) { Vertex l0pos=loddata[0][x]; float xx=(l0pos.x-spherepos.x); float yy=(l0pos.y-spherepos.y); float zz=(l0pos.z-spherepos.z); float xx2=(l0pos.x-spherepos2.x); float yy2=(l0pos.y-spherepos2.y); float zz2=(l0pos.z-spherepos2.z); float dist=sqrt(xx*xx+yy*yy+zz*zz); float dist2=sqrt(xx2*xx2+yy2*yy2+zz2*zz2); float powah=r0(diam-dist)/diam; // 0..1 sphere float powah2=r0(diam-dist2)/diam; float lod=clamp((powah+powah2)*powr); //lod=clamp(powr); float lodfract=lod*(float)MAX_LOD_REDUCTION; int bufnum=(int)floor(lodfract); lodfract=fmod(lodfract, 1.0); c[x*3+0]=c[x*3+1]=c[x*3+2]=clamp((lod-0.1)*4.0); // calc lodded pos if (lod==0.0) { v[x]=l0pos; lodlevels[x]=0; } else if (lod==1.0) { v[x]=loddata[MAX_LOD_REDUCTION][x]; lodlevels[x]=1; } else { Vertex l0=loddata[bufnum][x]; Vertex l1=loddata[bufnum+1][x]; v[x].x = l0.x*(1.0-lodfract)+l1.x*(lodfract); v[x].y = l0.y*(1.0-lodfract)+l1.y*(lodfract); v[x].z = l0.z*(1.0-lodfract)+l1.z*(lodfract); lodlevels[x]=1; } // push Vertex pd=new_v(v[x].x-spherepos.x, v[x].y-spherepos.y, v[x].z-spherepos.z); Vertex pd2=new_v(v[x].x-spherepos2.x, v[x].y-spherepos2.y, v[x].z-spherepos2.z); normalize(&pd); normalize(&pd2); v[x].x+=push*powah*pd.x+push*powah2*pd2.x; v[x].y+=push*powah*pd.y+push*powah2*pd2.y; v[x].z+=push*powah*pd.z+push*powah2*pd2.z; // little something for normal n[x]=new_v(0.0, 0.00001, 0.0); } // calc normals for (int x=0; x<fc; x++) { Vertex fnorm; Vertex *v1, *v2, *v3; Vertex *n1, *n2, *n3; v1=&v[i[x*3+0]]; v2=&v[i[x*3+1]]; v3=&v[i[x*3+2]]; n1=&n[i[x*3+0]]; n2=&n[i[x*3+1]]; n3=&n[i[x*3+2]]; calc_fnorm_nn(v1, v2, v3, &fnorm); n1->x+=fnorm.x; n1->y+=fnorm.y; n1->z+=fnorm.z; n2->x+=fnorm.x; n2->y+=fnorm.y; n2->z+=fnorm.z; n3->x+=fnorm.x; n3->y+=fnorm.y; n3->z+=fnorm.z; } // normalize normals, for lod 0 use original normal for (int x=0; x<vc; x++) { if (lodlevels[x]==0) n[x]=loddermesh->groups[group]->normals[x]; else normalize(&n[x]); } // render arrays // glUniform1fARB(glGetUniformLocationARB(shader, "depthmult"), 1.0); glue_disableallarrays(); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, v); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, n); /* Vertex *t=loddermesh->groups[group]->texcoords; if (t) { glClientActiveTexture(GL_TEXTURE0_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_FLOAT, 0, t); }*/ // alkup. verteksit texturekoordinaateiks glClientActiveTexture(GL_TEXTURE1_ARB); glActiveTexture(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_FLOAT, 0, loddata[0]); glDrawElements(GL_TRIANGLES, fc*3, GL_UNSIGNED_INT, i); /* // wireframe //glUniform1fARB(glGetUniformLocationARB(shader, "depthmult"), 0.0); //renderflags(GLUE_BLEND_ALPHAADD|GLUE_CHECK_DEPTH); renderflags(GLUE_BLEND|GLUE_CHECK_DEPTH); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glEnable(GL_POLYGON_OFFSET_LINE); glPolygonOffset(1.0, 1.0); //glEnable(GL_LINE_SMOOTH); glLineWidth(glueXres/320); glueDisabletexture(); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, c); glDrawElements(GL_TRIANGLES, fc*3, GL_UNSIGNED_INT, i); glue_disableallarrays(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_POLYGON_OFFSET_LINE); */ glue_disableallarrays(); tmpfree(lodlevels); tmpfree(c); tmpfree(n); tmpfree(v); }
arg_t _execve(void) { /* We aren't re-entrant where this matters */ uint8_t hdr[16]; staticfast inoptr ino; char **nargv; /* In user space */ char **nenvp; /* In user space */ struct s_argblk *abuf, *ebuf; int argc; uint16_t progptr; uint16_t progload; staticfast uint16_t top; uint16_t bin_size; /* Will need to be bigger on some cpus */ uint16_t bss; top = ramtop; if (!(ino = n_open_lock(name, NULLINOPTR))) return (-1); if (!((getperm(ino) & OTH_EX) && (ino->c_node.i_mode & F_REG) && (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) { udata.u_error = EACCES; goto nogood; } setftime(ino, A_TIME); udata.u_offset = 0; udata.u_count = 16; udata.u_base = hdr; udata.u_sysio = true; readi(ino, 0); if (udata.u_done != 16) { udata.u_error = ENOEXEC; goto nogood; } if (!header_ok(hdr)) { udata.u_error = ENOEXEC; goto nogood2; } progload = hdr[7] << 8; if (progload == 0) progload = PROGLOAD; top = *(uint16_t *)(hdr + 8); if (top == 0) /* Legacy 'all space' binary */ top = ramtop; else /* Requested an amount, so adjust for the base */ top += progload; bss = *(uint16_t *)(hdr + 14); /* Binary doesn't fit */ /* FIXME: review overflows */ bin_size = ino->c_node.i_size; progptr = bin_size + 1024 + bss; if (progload < PROGLOAD || top - progload < progptr || progptr < bin_size) { udata.u_error = ENOMEM; goto nogood2; } udata.u_ptab->p_status = P_NOSLEEP; /* If we made pagemap_realloc keep hold of some defined area we could in theory just move the arguments up or down as part of the process - that would save us all this hassle but replace it with new hassle */ /* Gather the arguments, and put them in temporary buffers. */ abuf = (struct s_argblk *) tmpbuf(); /* Put environment in another buffer. */ ebuf = (struct s_argblk *) tmpbuf(); /* Read args and environment from process memory */ if (rargs(argv, abuf) || rargs(envp, ebuf)) goto nogood3; /* SN */ /* This must be the last test as it makes changes if it works */ /* FIXME: once we sort out chmem we can make stack and data two elements. We never allocate 'code' as there is no split I/D */ /* This is only safe from deadlocks providing pagemap_realloc doesn't sleep */ if (pagemap_realloc(0, top - MAPBASE, 0)) goto nogood3; /* From this point on we are commmited to the exec() completing */ /* Core dump and ptrace permission logic */ #ifdef CONFIG_LEVEL_2 /* Q: should uid == 0 mean we always allow core */ if ((!(getperm(ino) & OTH_RD)) || (ino->c_node.i_mode & (SET_UID | SET_GID))) udata.u_flags |= U_FLAG_NOCORE; else udata.u_flags &= ~U_FLAG_NOCORE; #endif udata.u_top = top; udata.u_ptab->p_top = top; /* setuid, setgid if executable requires it */ if (ino->c_node.i_mode & SET_UID) udata.u_euid = ino->c_node.i_uid; if (ino->c_node.i_mode & SET_GID) udata.u_egid = ino->c_node.i_gid; /* FIXME: In the execve case we may on some platforms have space below PROGLOAD to clear... */ /* We are definitely going to succeed with the exec, * so we can start writing over the old program */ uput(hdr, (uint8_t *)progload, 16); /* At this point, we are committed to reading in and * executing the program. This call must not block. */ close_on_exec(); /* * Read in the rest of the program, block by block. We rely upon * the optimization path in readi to spot this is a big move to user * space and move it directly. */ progptr = progload + 16; if (bin_size > 16) { bin_size -= 16; udata.u_base = (uint8_t *)progptr; /* We copied the first block already */ udata.u_count = bin_size; udata.u_sysio = false; readi(ino, 0); if (udata.u_done != bin_size) goto nogood4; progptr += bin_size; } /* Wipe the memory in the BSS. We don't wipe the memory above that on 8bit boxes, but defer it to brk/sbrk() */ uzero((uint8_t *)progptr, bss); /* Set initial break for program */ udata.u_break = (int)ALIGNUP(progptr + bss); /* Turn off caught signals */ memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec)); // place the arguments, environment and stack at the top of userspace memory, // Write back the arguments and the environment nargv = wargs(((char *) top - 2), abuf, &argc); nenvp = wargs((char *) (nargv), ebuf, NULL); // Fill in udata.u_name with program invocation name uget((void *) ugetw(nargv), udata.u_name, 8); memcpy(udata.u_ptab->p_name, udata.u_name, 8); tmpfree(abuf); tmpfree(ebuf); i_deref(ino); /* Shove argc and the address of argv just below envp FIXME: should flip them in crt0.S of app for R2L setups so we can get rid of the ifdefs */ #ifdef CONFIG_CALL_R2L /* Arguments are stacked the 'wrong' way around */ uputw((uint16_t) nargv, nenvp - 2); uputw((uint16_t) argc, nenvp - 1); #else uputw((uint16_t) nargv, nenvp - 1); uputw((uint16_t) argc, nenvp - 2); #endif /* Set stack pointer for the program */ udata.u_isp = nenvp - 2; /* Start execution (never returns) */ udata.u_ptab->p_status = P_RUNNING; doexec(progload); /* tidy up in various failure modes */ nogood4: /* Must not run userspace */ ssig(udata.u_ptab, SIGKILL); nogood3: udata.u_ptab->p_status = P_RUNNING; tmpfree(abuf); tmpfree(ebuf); nogood2: nogood: i_unlock_deref(ino); return (-1); }
void mbr_parse(char letter) { boot_record_t *br; uint8_t i, seen = 0; uint32_t ep_offset = 0, br_offset = 0; uint8_t next = 0; kprintf("hd%c: ", letter); /* allocate temporary memory */ br = (boot_record_t *)tmpbuf(); blk_op.is_read = true; blk_op.is_user = false; blk_op.addr = (uint8_t *)br; blk_op.lba = 0; do{ blk_op.nblock = 1; if(!blk_op.blkdev->transfer() || le16_to_cpu(br->signature) != MBR_SIGNATURE){ #ifdef CONFIG_MBR_OFFSET if (blk_op.lba == 0) { /* failed to find MBR on block 0. Go round again but this time look at the fall-back location for this badly-behaved media */ blk_op.lba = CONFIG_MBR_OFFSET; continue; } #endif break; } /* avoid an infinite loop where extended boot records form a loop */ if(seen >= 50) break; if(seen == 1){ /* we just loaded the first extended boot record */ ep_offset = blk_op.lba; next = 4; kputs("< "); } br_offset = blk_op.lba; blk_op.lba = 0; for(i=0; i<MBR_ENTRY_COUNT && next < MAX_PARTITIONS; i++){ switch(br->partition[i].type_chs_last[0]){ #ifdef CONFIG_GPT case MBR_GPT_PROTECTED_TYPE: // TODO assert next is zero (unless hybrid...) parse_gpt((uint8_t *) br, i); goto out; #endif case 0: break; case 0x05: case 0x0f: case 0x85: /* Extended boot record, or chained table; in principle a drive should contain at most one extended partition so this code is OK even for parsing the MBR. Chained EBR addresses are relative to the start of the extended partiton. */ blk_op.lba = ep_offset + le32_to_cpu(br->partition[i].lba_first); if(next >= 4) break; /* we include all primary partitions but we deliberately knobble the size in order to prevent catastrophic accidents */ br->partition[i].lba_count = cpu_to_le32(2L); /* fall through */ default: /* Regular partition: In EBRs these are relative to the EBR (not the disk, nor the extended partition) */ blk_op.blkdev->lba_first[next] = br_offset + le32_to_cpu(br->partition[i].lba_first); blk_op.blkdev->lba_count[next] = le32_to_cpu(br->partition[i].lba_count); next++; kprintf("hd%c%d ", letter, next); } } seen++; }while(blk_op.lba); if(ep_offset && next >= 4) kputs("> "); out: /* release temporary memory */ tmpfree(br); }
void glueMpeg2_get(Mpeg2 *mpg, Texture *dst, int sync_channel, float fps, int border, int skip_frames, int reset_on_error) { unsigned char *tmpbuf; int framecnt=0; float curtime; #ifdef USE_FMODEX if(sync_channel==-1) // no audio sync curtime = timeGetTime(); else // get time from audio channel curtime = fmod_gettick_channel(sync_channel)+(1000.0/fps); #else curtime = timeGetTime(); #endif if (mpg->end==1) { glueMpeg2_reset(mpg); } if (mpg->prevtime==0) { getframe(mpg, dst); if (mpg->end==2) { glueMpeg2_reset(mpg); return; } if (mpg->end==3) { if (reset_on_error) glueMpeg2_reset(mpg); return; } } else if (curtime-mpg->prevtime < 1000.0/fps) return; else { int x; framecnt=(curtime-mpg->prevtime)/(1000.0/fps); if (skip_frames==0 && framecnt>1) framecnt=1; for (x=0; x<framecnt; x++) { getframe(mpg, dst); if (mpg->end==2) { glueMpeg2_reset(mpg); return; } if (mpg->end==3) { if (reset_on_error) glueMpeg2_reset(mpg); return; } } } if (mpg->prevtime==0) mpg->prevtime=curtime; else mpg->prevtime+=1000.0/fps*framecnt; //mpg->prevtime=timeGetTime(); tmpbuf=tmpmalloc(dst->xres*dst->yres*4); if (mpg->info->display_fbuf) { int w, h; w=mpg->info->sequence->width; h=mpg->info->sequence->height; if (dst->xres==w && dst->yres==h && (!border)) { glueReloadtexture(dst, mpg->info->display_fbuf->buf[0]); } else { int x; memset(tmpbuf, 0, dst->xres*dst->yres*4); if (dst->xres < w || dst->yres < h) glueErrorf("erreur: ur texture too small for ur videoz (%ix%i vs %ix%i)", w, h, dst->xres, dst->yres); for (x=0; x<h; x++) memcpy(tmpbuf+x*dst->xres*4, mpg->info->display_fbuf->buf[0]+x*w*4, dst->xres*4); if (border) { for (x=0; x<w; x++) { blask(tmpbuf, x); blask(tmpbuf, x+(h-1)*dst->xres); } for (x=0; x<h; x++) { blask(tmpbuf, x*dst->xres); blask(tmpbuf, x*dst->xres+w-1); } } dst->scale.x=(float)w/dst->xres; dst->scale.y=(float)h/dst->yres; glueReloadtexture(dst, tmpbuf); } } tmpfree(tmpbuf); }
arg_t _execve(void) { /* Not ideal on stack */ struct binfmt_flat binflat; inoptr ino; char **nargv; /* In user space */ char **nenvp; /* In user space */ struct s_argblk *abuf, *ebuf; int argc; uint32_t bin_size; /* Will need to be bigger on some cpus */ uaddr_t progbase, top; uaddr_t go; uint32_t true_brk; if (!(ino = n_open_lock(name, NULLINOPTR))) return (-1); if (!((getperm(ino) & OTH_EX) && (ino->c_node.i_mode & F_REG) && (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) { udata.u_error = EACCES; goto nogood; } setftime(ino, A_TIME); udata.u_offset = 0; udata.u_count = sizeof(struct binfmt_flat); udata.u_base = (void *)&binflat; udata.u_sysio = true; readi(ino, 0); if (udata.u_done != sizeof(struct binfmt_flat)) { udata.u_error = ENOEXEC; goto nogood; } /* FIXME: ugly - save this as valid_hdr modifies it */ true_brk = binflat.bss_end; /* Hard coded for our 68K format. We don't quite use the ucLinux names, we don't want to load a ucLinux binary in error! */ if (memcmp(binflat.magic, "bFLT", 4) || !valid_hdr(ino, &binflat)) { udata.u_error = ENOEXEC; goto nogood2; } /* Memory needed */ bin_size = binflat.bss_end + binflat.stack_size; /* Overflow ? */ if (bin_size < binflat.bss_end) { udata.u_error = ENOEXEC; goto nogood2; } /* Gather the arguments, and put them in temporary buffers. */ abuf = (struct s_argblk *) tmpbuf(); /* Put environment in another buffer. */ ebuf = (struct s_argblk *) tmpbuf(); /* Read args and environment from process memory */ if (rargs(argv, abuf) || rargs(envp, ebuf)) goto nogood3; /* This must be the last test as it makes changes if it works */ /* FIXME: need to update this to support split code/data and to fix stack handling nicely */ /* FIXME: ENOMEM fix needs to go to 16bit ? */ if ((udata.u_error = pagemap_realloc(0, bin_size, 0)) != 0) goto nogood3; /* Core dump and ptrace permission logic */ #ifdef CONFIG_LEVEL_2 /* Q: should uid == 0 mean we always allow core */ if ((!(getperm(ino) & OTH_RD)) || (ino->c_node.i_mode & (SET_UID | SET_GID))) udata.u_flags |= U_FLAG_NOCORE; else udata.u_flags &= ~U_FLAG_NOCORE; #endif udata.u_codebase = progbase = pagemap_base(); /* From this point on we are commmited to the exec() completing so we can start writing over the old program */ uput(&binflat, (uint8_t *)progbase, sizeof(struct binfmt_flat)); /* setuid, setgid if executable requires it */ if (ino->c_node.i_mode & SET_UID) udata.u_euid = ino->c_node.i_uid; if (ino->c_node.i_mode & SET_GID) udata.u_egid = ino->c_node.i_gid; top = progbase + bin_size; udata.u_top = top; udata.u_ptab->p_top = top; // kprintf("user space at %p\n", progbase); // kprintf("top at %p\n", progbase + bin_size); bin_size = binflat.reloc_start + 4 * binflat.reloc_count; go = (uint32_t)progbase + binflat.entry; close_on_exec(); /* * Read in the rest of the program, block by block. We rely upon * the optimization path in readi to spot this is a big move to user * space and move it directly. */ if (bin_size > sizeof(struct binfmt_flat)) { /* We copied the header already */ bin_size -= sizeof(struct binfmt_flat); udata.u_base = (uint8_t *)progbase + sizeof(struct binfmt_flat); udata.u_count = bin_size; udata.u_sysio = false; readi(ino, 0); if (udata.u_done != bin_size) goto nogood4; } /* Header isn't counted in relocations */ relocate(&binflat, progbase, bin_size); /* This may wipe the relocations */ uzero((uint8_t *)progbase + binflat.data_end, binflat.bss_end - binflat.data_end + binflat.stack_size); /* Use of brk eats into the stack allocation */ /* Use the temporary we saved (hack) as we mangled bss_end */ udata.u_break = udata.u_codebase + true_brk; /* Turn off caught signals */ memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec)); /* place the arguments, environment and stack at the top of userspace memory. */ /* Write back the arguments and the environment */ nargv = wargs(((char *) top - 4), abuf, &argc); nenvp = wargs((char *) (nargv), ebuf, NULL); /* Fill in udata.u_name with Program invocation name */ uget((void *) ugetl(nargv, NULL), udata.u_name, 8); memcpy(udata.u_ptab->p_name, udata.u_name, 8); tmpfree(abuf); tmpfree(ebuf); i_unlock_deref(ino); /* Shove argc and the address of argv just below envp */ uputl((uint32_t) nargv, nenvp - 1); uputl((uint32_t) argc, nenvp - 2); // Set stack pointer for the program udata.u_isp = nenvp - 2; /* * Sort of - it's a good way to deal with all the stupidity of * random 68K platforms we will have to handle, and a nice place * to stuff the signal trampoline 8) */ install_vdso(); // kprintf("Go = %p ISP = %p\n", go, udata.u_isp); doexec(go); nogood4: /* Must not run userspace */ ssig(udata.u_ptab, SIGKILL); nogood3: tmpfree(abuf); tmpfree(ebuf); nogood2: nogood: i_unlock_deref(ino); return (-1); }
void devide_init_drive(uint_fast8_t drive) { blkdev_t *blk; uint8_t *buffer; uint_fast8_t select; select = (drive & 1) ? 0xF0 : 0xE0; ide_select(drive); devide_writeb(ide_reg_devhead, select); kprintf("IDE drive %d: ", drive); #ifdef IDE_8BIT_ONLY if (IDE_IS_8BIT(drive)) { /* set 8-bit mode -- mostly only supported by CF cards */ if (!devide_wait(IDE_STATUS_READY)) goto out; devide_writeb(ide_reg_devhead, select); if (!devide_wait(IDE_STATUS_READY)) goto out; devide_writeb(ide_reg_features, 0x01); /* Enable 8-bit PIO transfer mode (CFA feature set only) */ devide_writeb(ide_reg_command, IDE_CMD_SET_FEATURES); } #endif /* confirm drive has LBA support */ if (!devide_wait(IDE_STATUS_READY)) goto out; /* send identify command */ devide_writeb(ide_reg_devhead, select); devide_writeb(ide_reg_command, IDE_CMD_IDENTIFY); /* allocate temporary sector buffer memory */ buffer = (uint8_t *)tmpbuf(); if (!devide_wait(IDE_STATUS_DATAREQUEST)) goto failout; blk_op.is_user = false; blk_op.addr = buffer; blk_op.nblock = 1; devide_read_data(); #ifdef CONFIG_IDE_BSWAP if(!(buffer[98] & 0x02)) { #else if(!(buffer[99] & 0x02)) { #endif kputs("LBA unsupported.\n"); goto failout; } blk = blkdev_alloc(); if(!blk) goto failout; blk->transfer = devide_transfer_sector; blk->flush = devide_flush_cache; blk->driver_data = drive & IDE_DRIVE_NR_MASK; if( !(((uint16_t*)buffer)[82] == 0x0000 && ((uint16_t*)buffer)[83] == 0x0000) || (((uint16_t*)buffer)[82] == 0xFFFF && ((uint16_t*)buffer)[83] == 0xFFFF) ){ /* command set notification is supported */ if(buffer[164] & 0x20){ /* write cache is supported */ blk->driver_data |= FLAG_WRITE_CACHE; } } /* read out the drive's sector count */ blk->drive_lba_count = le32_to_cpu(*((uint32_t*)&buffer[120])); /* done with our temporary memory */ tmpfree(buffer); /* Deselect the IDE, as we will re-select it in the partition scan and it may not recursively stack de-selections */ ide_deselect(); /* scan partitions */ blkdev_scan(blk, SWAPSCAN); return; failout: tmpfree(buffer); out: ide_deselect(); return; } void devide_init(void) { uint_fast8_t d; #ifdef IDE_HAS_RESET devide_reset(); #endif for(d=0; d < IDE_DRIVE_COUNT; d++) devide_init_drive(d); }
void pathfree(char *tb) { tmpfree(tb); }