int forward_seek_entry(int segment_id, byte ** ptr, unsigned long *map) { byte *tmp_ptr; unsigned long sector; int segment; int count; do { sector = get_sector(ptr, forward); segment = cvt2segment(sector); } while (sector != 0 && segment < segment_id); tmp_ptr = *ptr - 3; /* point to first sector >= segment_id */ /* Get all sectors in segment_id */ if (format_code == 4 && (sector & 0x800000) && segment == segment_id) { *map = EMPTY_SEGMENT; count = 32; } else { *map = 0; count = 0; while (sector != 0 && segment == segment_id) { *map |= cvt2map(sector); sector = get_sector(ptr, forward); segment = cvt2segment(sector); ++count; } } *ptr = tmp_ptr; return count; }
int get_clickshift(u32_t ksec, struct image_header *hdr) /* Get the click shift and special flags from kernel text. */ { char *textp; if ((textp= get_sector(ksec)) == nil) return 0; if (hdr->process.a_flags & A_PAL) textp+= hdr->process.a_hdrlen; click_shift= * (u16_t *) (textp + CLICK_OFF); k_flags= * (u16_t *) (textp + FLAGS_OFF); if ((k_flags & ~K_ALL) != 0) { printf("%s requires features this monitor doesn't offer\n", hdr->name); return 0; } if (click_shift < HCLICK_SHIFT || click_shift > 16) { printf("%s click size is bad\n", hdr->name); errno= 0; return 0; } click_size= 1 << click_shift; return 1; }
void EditorSectorsMenu::create_sector() { auto level = Editor::current()->get_level(); auto new_sector = SectorParser::from_nothing(*level); if (!new_sector) { log_warning << "Failed to create a new sector." << std::endl; return; } // Find an unique name std::string sector_name; int num = 2; do { sector_name = "sector" + std::to_string(num); num++; } while ( level->get_sector(sector_name) ); new_sector->set_name(sector_name); level->add_sector(std::move(new_sector)); Editor::current()->load_sector(sector_name); MenuManager::instance().clear_menu_stack(); Editor::current()->m_reactivate_request = true; }
int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit) /* Read *size bytes starting at virtual sector *vsec to memory at *addr. */ { char *buf; size_t cnt, n; cnt= 0; while (*size > 0) { if (cnt == 0) { if ((buf= get_sector((*vsec)++)) == nil) return 0; cnt= SECTOR_SIZE; } if (*addr + click_size > limit) { errno= ENOMEM; return 0; } n= click_size; if (n > cnt) n= cnt; raw_copy(*addr, mon2abs(buf), n); *addr+= n; *size-= n; buf+= n; cnt-= n; } /* Zero extend to a click. */ n= align(*addr, click_size) - *addr; raw_clear(*addr, n); *addr+= n; *size-= n; return 1; }
int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub) { struct burn_drive *d = o->drive; unsigned char subs[96]; unsigned char *data; data = get_sector(o, t, t->mode); if (data == NULL) return 0; /* ts A61010 */ if (convert_data(o, t, t->mode, data) <= 0) return 0; /* ts A61031 */ if ((t->open_ended || t->end_on_premature_eoi) && t->track_data_done) { unget_sector(o, t->mode); return 2; } /* ts A61219 : allow track without .entry */ if (t->entry == NULL) ; else if (!t->source->read_sub) subcode_user(o, subs, t->entry->point, t->entry->control, 1, &t->isrc, psub); else if (!t->source->read_sub(t->source, subs, 96)) subcode_user(o, subs, t->entry->point, t->entry->control, 1, &t->isrc, psub); convert_subs(o, t->mode, subs, data); if (sector_headers(o, data, t->mode, 0) <= 0) return 0; sector_common(++) return 1; }
int backwards_seek_entry(int segment_id, byte ** ptr, unsigned long *map) { unsigned long sector; int segment; int count; *map = 0; if (*ptr > bad_sector_map) { do { sector = get_sector(ptr, backward); segment = cvt2segment(sector); } while (*ptr > bad_sector_map && segment > segment_id); count = 0; if (segment > segment_id) { /* at start of list, no entry found */ } else if (segment < segment_id) { /* before smaller entry, adjust for overshoot */ *ptr += 3; } else { /* get all sectors in segment_id */ if (format_code == 4 && (sector & 0x800000)) { *map = EMPTY_SEGMENT; count = 32; } else { do { *map |= cvt2map(sector); ++count; if (*ptr <= bad_sector_map) { break; } sector = get_sector(ptr, backward); segment = cvt2segment(sector); } while (segment == segment_id); if (segment < segment_id) { *ptr += 3; } } } } else { count = 0; } return count; }
void Level::add_sector(std::unique_ptr<Sector> sector) { Sector* test = get_sector(sector->get_name()); if (test != nullptr) { throw std::runtime_error("Trying to add 2 sectors with same name"); } else { m_sectors.push_back(std::move(sector)); } }
int TRKCACHE::write_sector(unsigned sec, unsigned char *data) { const SECHDR *h = get_sector(sec); if (!h || !h->data) return 0; unsigned sz = h->datlen; if(h->data != data) memcpy(h->data, data, sz); *(unsigned short*)(h->data+sz) = (unsigned short)wd93_crc(h->data-1, sz+1); return sz; }
static size_t fat_read(struct fat_fs *filesystem, uint32_t cluster_no, uint8_t *buf, size_t byte_count, size_t offset) { uint32_t cur_cluster = cluster_no; size_t cluster_size = filesystem->bytes_per_sector * filesystem->sectors_per_cluster; size_t file_loc = 0; int buf_ptr = 0; while(cur_cluster < 0x0ffffff8) { if(( file_loc + cluster_size) > offset) { if( file_loc < (offset + byte_count)) { // load this cluster, as it contains the requested file uint32_t sector = get_sector(filesystem, cur_cluster); uint8_t * r_buf = (uint8_t*)malloc(cluster_size); int ret = sd_read(r_buf, cluster_size, sector); // check for error if(ret < 0) { return ret; } int len; int c_ptr; // what part of this sector is in the file if(offset >= file_loc) { // first cluster of file buf_ptr = 0; c_ptr = offset - file_loc; len = byte_count; if(len > (int)cluster_size) { len = cluster_size; } } else { // not first cluster of file c_ptr = 0; len = byte_count - buf_ptr; if(len > (int)cluster_size) { len = cluster_size; } if(len > (int)(byte_count - buf_ptr)) { len = byte_count - buf_ptr; } } memcpy(buf + buf_ptr, r_buf + c_ptr, len); free(r_buf); buf_ptr += len; } } cur_cluster = get_next_fat_entry( filesystem, cur_cluster); file_loc += cluster_size; } return buf_ptr; }
int hal_nvm_init_sector(HAL_NVM_HANDLE handle, unsigned long address) { int sector = get_sector(address); int rv = HAL_NVM_E_SUCCESS; FLASH_Unlock(); if (FLASH_EraseSector(sector, VoltageRange_3) != FLASH_COMPLETE) { rv = HAL_NVM_E_ERROR; } FLASH_Lock(); return rv; }
int sector_lout(struct burn_write_opts *o, unsigned char control, int mode) { struct burn_drive *d = o->drive; unsigned char subs[96]; unsigned char *data; data = get_sector(o, NULL, mode); if (!data) return 0; /* ts A61010 */ if (convert_data(o, NULL, mode, data) <= 0) return 0; subcode_lout(o, control, subs); convert_subs(o, mode, subs, data); if (sector_headers(o, data, mode, 0) <= 0) return 0; sector_common(++) return 1; }
int sector_toc(struct burn_write_opts *o, int mode) { struct burn_drive *d = o->drive; unsigned char *data; unsigned char subs[96]; data = get_sector(o, NULL, mode); if (data == NULL) return 0; /* ts A61010 */ if (convert_data(o, NULL, mode, data) <= 0) return 0; subcode_toc(d, mode, subs); convert_subs(o, mode, subs, data); if (sector_headers(o, data, mode, 1) <= 0) return 0; sector_common(++) return 1; }
int sector_pregap(struct burn_write_opts *o, unsigned char tno, unsigned char control, int mode) { struct burn_drive *d = o->drive; unsigned char *data; unsigned char subs[96]; data = get_sector(o, NULL, mode); if (data == NULL) return 0; /* ts A61010 */ if (convert_data(o, NULL, mode, data) <= 0) return 0; subcode_user(o, subs, tno, control, 0, NULL, 1); convert_subs(o, mode, subs, data); if (sector_headers(o, data, mode, 0) <= 0) return 0; sector_common(--) return 1; }
void get_data(DRIVE_PARAMS *drive_params, uint8_t track[]) { int block; int rc; block = (get_cyl() * drive_params->num_head + get_head()) * drive_params->num_sectors + get_sector(); if (lseek(drive_params->ext_fd, block * drive_params->sector_size, SEEK_SET) == -1) { msg(MSG_FATAL, "Failed to seek to sector in extracted data file %s\n", strerror(errno)); exit(1); } if ((rc = read(drive_params->ext_fd, track, drive_params->sector_size)) != drive_params->sector_size) { msg(MSG_FATAL, "Failed to read extracted data file rc %d %s\n", rc, rc == -1 ? strerror(errno): ""); exit(1); }; }
int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit) /* Read *size bytes starting at virtual sector *vsec to memory at *addr. */ { char *buf; size_t cnt, n; cnt= 0; while (*size > 0) { if (cnt == 0) { if ((buf= get_sector((*vsec)++)) == nil) return 0; cnt= SECTOR_SIZE; } if (*addr + click_size > limit) { DEBUGEXTRA(("get_segment: out of memory; " "addr=0x%lx; limit=0x%lx; size=%lx\n", *addr, limit, size)); errno= ENOMEM; return 0; } n= click_size; if (n > cnt) n= cnt; DEBUGMAX(("raw_copy(0x%lx, 0x%lx/0x%x, 0x%lx)... ", *addr, mon2abs(buf), buf, n)); raw_copy(*addr, mon2abs(buf), n); DEBUGMAX(("done\n")); *addr+= n; *size-= n; buf+= n; cnt-= n; } /* Zero extend to a click. */ n= align(*addr, click_size) - *addr; DEBUGMAX(("raw_clear(0x%lx, 0x%lx)... ", *addr, n)); raw_clear(*addr, n); DEBUGMAX(("done\n")); *addr+= n; *size-= n; return 1; }
void put_bad_sector_entry(int segment_id, unsigned long new_map) { byte *ptr = bad_sector_map; int count; int new_count; unsigned long map; if (format_code == 3 || format_code == 4) { count = forward_seek_entry(segment_id, &ptr, &map); new_count = count_ones(new_map); /* If format code == 4 put empty segment instead of 32 bad sectors. */ if (new_count == 32 && format_code == 4) { new_count = 1; } if (count != new_count) { /* insert (or delete if < 0) new_count - count entries. * Move trailing part of list including terminating 0. */ byte *hi_ptr = ptr; do { } while (get_sector(&hi_ptr, forward) != 0); memmove(ptr + new_count, ptr + count, hi_ptr - (ptr + count)); } if (new_count == 1 && new_map == EMPTY_SEGMENT) { put_sector(&ptr, 0x800001 + segment_id * SECTORS_PER_SEGMENT); } else { int i = 0; while (new_map) { if (new_map & 1) { put_sector(&ptr, 1 + segment_id * SECTORS_PER_SEGMENT + i); } ++i; new_map >>= 1; } } } else {
static uint32_t fat_get_next_bdev_block_num(uint32_t f_block_idx, fs_file *s, void *opaque, int add_blocks) { struct fat_file_block_offset *ffbo = (struct fat_file_block_offset *)opaque; // Iterate through the cluster chain until we reach the appropriate one while((ffbo->f_block != f_block_idx) && (ffbo->cluster < 0x0ffffff8)) { ffbo->cluster = get_next_fat_entry((struct fat_fs *)s->fs, ffbo->cluster); ffbo->f_block++; } if(ffbo->cluster < 0x0ffffff8) return get_sector((struct fat_fs *)s->fs, ffbo->cluster); else { if(add_blocks) { printf("FAT: request to extend cluster chain not currently supported\r\n"); } s->flags |= EOF; return 0xffffffff; } }
int main(int, char** argv) { FILE* file; int result = get_sector(0x80, 0, 0, 1, sector); if(0 != result) { fprintf(stderr, "%s: error reading sector\n", argv[0]); result = 1; } else if((file = fopen(file_name, "wb")) == 0) { fprintf(stderr, "%s: error opening %s\n", argv[0], file_name); result = 1; } else { fwrite(sector, sector_size, 1, file); fclose(file); result = 0; } return result; }
long rread(Rfile tpf, void *buf, long count) /* Read a buffer from an open ram-disk file. */ { char ***platter; char **track; char *data; int i; int ssize, so; int flags; long filept; long readin; long fsize; flags = tpf->flags; if (!(flags&TF_OPEN)) { rerr = Err_file_not_open; return(0); } if (!(flags&TF_READ)) { rerr = Err_read; return(0); } data = buf; readin = 0; filept = tpf->filep; fsize = tpf->size; if ((tpf->filep = filept+count) > fsize) { rerr = Err_eof; if ((count = fsize-filept) <= 0) return(0); } platter = tpf->platters + get_platter(filept); for (;;) { i = get_track(filept); track = *platter + i; for ( ; i< TRD_TRACK; i++) { so = get_sector(filept); ssize = TRD_SECTOR - so; if (count > ssize) { memcpy(data, *track + so, ssize); readin += ssize; data += ssize; count -= ssize; filept += ssize; } else { memcpy(data, *track + so, (size_t)count); return(readin+count); } track++; } platter++; } }
int main(int argc, char* argv[]) { char q[512]; MYSQL_ROW row; MYSQL_RES* res; int err = init_network(); if (err) { return err; } for (int year = 1990; year <= 2011; year++) { std::cout << "Querying " << year << "\n"; snprintf(q, 512, "select count(value) from entries where year=%d and inserted>(select updated from visualizations where name='GAP2' and year=%d)", year, year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } res = mysql_use_result(mysql); if ((row = mysql_fetch_row(res)) == 0 || atoi(row[0]) == 0) { mysql_free_result(res); continue; } mysql_free_result(res); err = read_network(year); if (err) { return err; } std::cout << "Calculating " << year << "\n"; Basetype* in_flow = create_array(0); Basetype* out_flow = create_array(0); int regions_size = regions.size(); Basetype* total_output = new Basetype[regions_size]; for (int r = 0; r < regions_size; r++) { total_output[r] = 0; } for (int v = 0; v < network_size; v++) { for (int w = 0; w < network_size; w++) { in_flow[v] += flows[w][v]; out_flow[v] += flows[v][w]; } total_output[get_region(v)] += out_flow[v]; } int sectors_size = sectors.size(); Basetype** in_flow_by_sector = new Basetype*[sectors_size]; for (int i = 0; i < sectors_size; i++) { in_flow_by_sector[i] = create_array(0); } for (int v = 0; v < network_size; v++) { for (int w = 0; w < network_size; w++) { in_flow_by_sector[get_sector(v)][w] += flows[v][w]; } } snprintf(q, 512, "delete from visualization_data where visualization in (select id from visualizations where (name='GAP1' or name='GAP2') and year=%d)", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } snprintf(q, 512, "select id from visualizations where name='GAP1' and year=%d", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } res = mysql_use_result(mysql); row = mysql_fetch_row(res); int id1 = atoi(row[0]); mysql_free_result(res); snprintf(q, 512, "select id from visualizations where name='GAP2' and year=%d", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } res = mysql_use_result(mysql); row = mysql_fetch_row(res); int id2 = atoi(row[0]); mysql_free_result(res); for (int r = 0; r < regions_size; r++) { Basetype* damage1 = create_array(0); Basetype* damage2 = create_array(0); int js; #pragma omp parallel default(shared) private(js) { #pragma omp for schedule(guided) nowait for (js = 0; js < network_size; js++) { if (get_region(js) == r) { damage1[js] = 1; } else { for (int i = 0; i < sectors_size; i++) { Basetype damage = flows[get_index(i, r)][js] / in_flow_by_sector[i][js]; if (damage1[js] < damage) { damage1[js] = damage; } } } } } #pragma omp parallel default(shared) private(js) { #pragma omp for schedule(guided) nowait for (js = 0; js < network_size; js++) { if (get_region(js) == r) { damage2[js] = 1; } else { for (int i = 0; i < sectors_size; i++) { Basetype damage = 0; for (int r = 0; r < regions_size; r++) { int ir = get_index(i, r); damage += damage1[ir] * flows[ir][js] / in_flow_by_sector[i][js]; } if (damage2[js] < damage) { damage2[js] = damage; } } } } } Basetype* region_damage1 = new Basetype[regions_size]; Basetype* region_damage2 = new Basetype[regions_size]; for (int r = 0; r < regions_size; r++) { region_damage1[r] = 0; region_damage2[r] = 0; } for (int js = 0; js < network_size; js++) { int s = get_region(js); if (total_output[s] > 0) { region_damage1[s] += damage1[js] * out_flow[js] / total_output[s]; region_damage2[s] += damage2[js] * out_flow[js] / total_output[s]; } } delete[] damage1; delete[] damage2; std::stringstream query1("insert into visualization_data (visualization, region_from, region_to, value) values ", std::ios_base::app | std::ios_base::out); bool first1 = true; std::stringstream query2("insert into visualization_data (visualization, region_from, region_to, value) values ", std::ios_base::app | std::ios_base::out); bool first2 = true; for (int s = 0; s < regions_size; s++) { region_damage1[s] = round(region_damage1[s] * 1000) / 1000; if (region_damage1[s] > 0) { if (first1) { first1 = false; } else { query1 << ","; } query1 << "(" << id1 << ",'" << regions[r] << "','" << regions[s] << "'," << region_damage1[s] << ")"; } region_damage2[s] = round(region_damage2[s] * 1000) / 1000; if (region_damage2[s] > 0) { if (first2) { first2 = false; } else { query2 << ","; } query2 << "(" << id2 << ",'" << regions[r] << "','" << regions[s] << "'," << region_damage2[s] << ")"; } } if (!first1) { if (mysql_query(mysql, query1.str().c_str())) { std::cerr << mysql_error(mysql) << "\n"; return -2; } } if (!first2) { if (mysql_query(mysql, query2.str().c_str())) { std::cerr << mysql_error(mysql) << "\n"; return -2; } } delete[] region_damage1; delete[] region_damage2; } delete[] in_flow; delete[] out_flow; free_double_array(flows); for (int i = 0; i < sectors_size; i++) { delete[] in_flow_by_sector[i]; } delete[] in_flow_by_sector; delete[] total_output; snprintf(q, 512, "update visualizations set updated=now() where (name='GAP1' or name='GAP2') and year=%d", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } } return disconnect(); }
int spimem_write_h(uint8_t spi_chip, uint32_t addr, uint8_t* data_buff, uint32_t size) { uint32_t size1, size2, low, dirty = 0, page, sect_num, check; if (size > 256) // Invalid size to write. return -2; if (addr > 0xFFFFF) // Invalid address to write to. return -2; low = addr & 0x000000FF; if ((size + low) > 256) // Requested write flows into a second page. { size1 = 256 - low; size2 = size - size1; } else { size1 = size; size2 = 0; } if ((addr + (size - 1)) > 0xFFFFF) // Address too high, can't write all requested bytes. { size1 = 256 - low; size2 = 0; } if (xSemaphoreTake(Spi0_Mutex, (TickType_t) 1) == pdTRUE) // Only Block for a single tick. { enter_atomic(); // Atomic operation begins. if(ready_for_command_h(spi_chip) != 1) { exit_atomic(); xSemaphoreGive(Spi0_Mutex); return -4; } page = get_page(addr); dirty = check_page(page); if(dirty) { sect_num = get_sector(addr); check = load_sector_into_spibuffer(spi_chip, sect_num); // if check != 4096, FAILURE_RECOVERY. check = update_spibuffer_with_new_page(addr, data_buff, size1); // if check != size1, FAILURE_RECOVERY. check = erase_sector_on_chip(spi_chip, sect_num); // FAILURE_RECOVERY check = write_sector_back_to_spimem(spi_chip); // FAILURE_RECOVERY } else { if(write_page_h(spi_chip, addr, data_buff, size1) != 1) { exit_atomic(); // Atomic operation ends. xSemaphoreGive(Spi0_Mutex); return -1; } } if(size2) // Requested write flows into a second page. { page = get_page(addr + size1); dirty = check_page(page); if(ready_for_command_h(spi_chip) != 1) { exit_atomic(); xSemaphoreGive(Spi0_Mutex); return size1; } if(dirty) { sect_num = get_sector(addr + size1); check = load_sector_into_spibuffer(spi_chip, sect_num); // if check != 4096, FAILURE_RECOVERY. if(check != 4096) return -4; check = update_spibuffer_with_new_page(addr + size1, (data_buff + size1), size2); // if check != size1, FAILURE_RECOVERY. if(check != size1) return -4; check = erase_sector_on_chip(spi_chip, sect_num); // FAILURE_RECOVERY if(check != 1) return -4; check = write_sector_back_to_spimem(spi_chip); // FAILURE_RECOVERY if(check == 0xFFFFFFFF) return -4; } else { if(write_page_h(spi_chip, addr + size1, (data_buff + size1), size2) != 1) { exit_atomic(); xSemaphoreGive(Spi0_Mutex); return size1; } } } exit_atomic(); xSemaphoreGive(Spi0_Mutex); return (size1 + size2); } else return -3; // SPI0 is currently being used or there is an error. }
bool TF20::process_cmd() { int drv, trk, sec, dst; uint8 *sctr, *sctw; switch(bufr[3]) { case FNC_RESET_P: case FNC_RESET_M: SET_HEAD(0); SET_CODE(ERR_SUCCESS); return true; case FNC_READ: drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4; drv += bufr[7] - 1; trk = bufr[8]; sec = bufr[9]; if(!disk_inserted(drv)) { // drive error SET_HEAD(0x80); for(int i = 0; i < 128; i++) { SET_DATA(0xff); } SET_CODE(ERR_DRIVE); return true; } if((sctr = get_sector(drv, trk, sec)) == NULL) { // read error SET_HEAD(0x80); for(int i = 0; i < 128; i++) { SET_DATA(0xff); } SET_CODE(ERR_READ); return true; } SET_HEAD(0x80); for(int i = 0; i < 128; i++) { SET_DATA(sctr[i]); } SET_CODE(ERR_SUCCESS); return true; case FNC_WRITE: drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4; drv += bufr[7] - 1; trk = bufr[8]; sec = bufr[9]; if(!disk_inserted(drv)) { // drive error SET_HEAD(0); SET_CODE(ERR_DRIVE); return true; } if(disk_protected(drv)) { // write protect SET_HEAD(0); SET_CODE(ERR_PROTECTED); return true; } if((sctw = get_sector(drv, trk, sec)) == NULL) { // write error SET_HEAD(0); SET_CODE(ERR_WRITE); return true; } // dont care write type for(int i = 0; i < 128; i++) { sctw[i] = bufr[11 + i]; } SET_HEAD(0); SET_CODE(ERR_SUCCESS); return true; case FNC_WRITEHST: SET_HEAD(0); SET_CODE(ERR_SUCCESS); return true; case FNC_COPY: drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4; drv += bufr[7] - 1; dst = (drv & ~1) | (~drv & 1); if(!disk_inserted(drv)) { // drive error SET_HEAD(0); SET_CODE(ERR_DRIVE); return true; } if(!disk_inserted(dst)) { // drive error SET_HEAD(0); SET_CODE(ERR_DRIVE); return true; } if(disk_protected(dst)) { // write protect SET_HEAD(0); SET_CODE(ERR_PROTECTED); return true; } for(trk = 0; trk < 40; trk++) { for(sec = 1; sec <= 64; sec++) { if((sctr = get_sector(drv, trk, sec)) == NULL) { // read error SET_HEAD(0); SET_CODE(ERR_READ); return true; } if((sctw = get_sector(dst, trk, sec)) == NULL) { // write error SET_HEAD(0); SET_CODE(ERR_WRITE); return true; } memcpy(sctw, sctr, 128); } SET_HEAD(2); SET_DATA(trk == 39 ? 0xff : 0); // high-order SET_DATA(trk == 39 ? 0xff : trk); // low-order SET_CODE(ERR_SUCCESS); } return true; case FNC_FORMAT: drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4; drv += bufr[7] - 1; if(!disk_inserted(drv)) { // drive error SET_HEAD(0); SET_CODE(ERR_DRIVE); return true; } if(disk_protected(drv)) { // write protect SET_HEAD(0); SET_CODE(ERR_PROTECTED); return true; } for(trk = 0; trk < 40; trk++) { for(sec = 1; sec <= 64; sec++) { if((sctw = get_sector(drv, trk, sec)) == NULL) { // write error SET_HEAD(0); SET_CODE(ERR_WRITE); return true; } memset(sctw, 0xe5, 128); } SET_HEAD(2); SET_DATA(trk == 39 ? 0xff : 0); // high-order SET_DATA(trk == 39 ? 0xff : trk); // low-order SET_CODE(ERR_SUCCESS); } return true; } // unknown command return false; }
int main(int argc, char* argv[]) { char q[512]; MYSQL_ROW row; MYSQL_RES* res; int err = init_network(); if (err) { return err; } for (int year = 1990; year <= 2011; year++) { std::cout << "Querying " << year << "\n"; snprintf(q, 512, "select count(value) from entries where year=%d and inserted>(select updated from visualizations where name='Flow Centrality' and year=%d)", year, year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } res = mysql_use_result(mysql); if((row = mysql_fetch_row(res)) == 0 || atoi(row[0]) == 0) { mysql_free_result(res); continue; } mysql_free_result(res); err = read_network(year); if (err) { return err; } std::cout << "Calculating " << year << "\n"; err = disconnect(); if (err) { return err; } Basetype* betweenness = create_array(0); Basetype* in_flow = create_array(0); Basetype* out_flow = create_array(0); for (int v = 0; v < network_size; v++) { for (int w = 0; w < network_size; w++) { in_flow[v] += flows[w][v]; out_flow[v] += flows[v][w]; } } // Algorithm according to "A space-efficient parallel algorithm for computing betweenness centrality in distributed memory", p. 2 int s; #pragma omp parallel default(none) shared(betweenness, flows, network_size, in_flow, std::cerr) { #pragma omp for schedule(guided) nowait for (s = 0; s < network_size; s++) { std::vector<int> S; std::queue<int> PQ; BasetypeInt* sigma; Basetype* delta; Basetype* dist; BasetypeInt** P; BasetypeInt* P_size; Basetype* pipe; sigma = create_array_int(0); sigma[s] = 1; delta = create_array(0); P = create_double_int_array(0); P_size = create_array_int(0); dist = create_array(-1); dist[s] = 0; pipe = create_array(0); pipe[s] = -1; PQ.push(s); while (!PQ.empty()) { int v = PQ.front(); PQ.pop(); for (std::vector<int>::iterator it = S.begin(); it != S.end(); it++) { if (*it == v) { S.erase(it); break; } } S.push_back(v); for (int w = 0; w < network_size; w++) { if (w != v && w != s && flows[v][w] > 0) { Basetype c_v_w = flows[v][w]; Basetype new_pipe; if (pipe[v] < 0) { new_pipe = c_v_w; } else { new_pipe = std::min(pipe[v], c_v_w); } if (pipe[w] < new_pipe || (pipe[w] == new_pipe && dist[w] > dist[v] + 1)) { // Better best path via v PQ.push(w); pipe[w] = new_pipe; dist[w] = dist[v] + 1; sigma[w] = 0; P_size[w] = 0; } if (pipe[w] == new_pipe && dist[w] == dist[v] + 1 && !in_array(v,P[w],P_size[w])) { // Some best path via v sigma[w] += sigma[v]; P[w][P_size[w]] = v; P_size[w]++; } } } } while (!S.empty()) { int w = S.back(); S.pop_back(); for (int v_index = 0; v_index < P_size[w]; v_index++) { int v = P[w][v_index]; delta[v] += ((1 + delta[w]) * (Basetype) sigma[v]) / (Basetype) sigma[w]; } if (w != s) { #pragma omp atomic betweenness[w] += delta[w]; } } delete[] delta; delete[] sigma; delete[] dist; delete[] P_size; free_double_int_array(P); delete[] pipe; } } err = connect(); if (err) { return err; } snprintf(q, 512, "delete from visualization_data where visualization in (select id from visualizations where name='Flow Centrality' and year=%d)", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } snprintf(q, 512, "select id from visualizations where name='Flow Centrality' and year=%d", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } res = mysql_use_result(mysql); row = mysql_fetch_row(res); int id = atoi(row[0]); mysql_free_result(res); std::stringstream query("insert into visualization_data (visualization, sector_from, region_from, value) values ", std::ios_base::app | std::ios_base::out); for (int js = 0; js < network_size; js++) { if (js > 0) { query << ","; } query << "(" << id << ",'" << sectors[get_sector(js)] << "','" << regions[get_region(js)] << "'," << betweenness[js] << ")"; } if (mysql_query(mysql, query.str().c_str())) { std::cerr << mysql_error(mysql) << "\n"; return -2; } snprintf(q, 512, "update visualizations set updated=now() where name='Flow Centrality' and year=%d", year); if (mysql_query(mysql, q)) { std::cerr << mysql_error(mysql) << "\n"; return -2; } delete[] betweenness; free_double_array(flows); } return 0; }
/* ---------------------------------------------------------------------------- * Handles the events for the area editor. */ void area_editor::handle_controls(const ALLEGRO_EVENT &ev) { if(fade_mgr.is_fading()) return; gui->handle_event(ev); //Update mouse cursor in world coordinates. if( ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_WARPED || ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN || ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP ) { mouse_cursor_x = ev.mouse.x / cam_zoom - cam_x - (gui_x / 2 / cam_zoom); mouse_cursor_y = ev.mouse.y / cam_zoom - cam_y - (scr_h / 2 / cam_zoom); lafi::widget* wum; if(!is_mouse_in_gui(ev.mouse.x, ev.mouse.y)) { wum = NULL; } else { wum = gui->get_widget_under_mouse(ev.mouse.x, ev.mouse.y); } ((lafi::label*) gui->widgets["lbl_status_bar"])->text = ( wum ? wum->description : "(" + i2s(mouse_cursor_x) + "," + i2s(mouse_cursor_y) + ")" ); } //Moving vertexes, camera, etc. if(ev.type == ALLEGRO_EVENT_MOUSE_AXES) { if( !is_mouse_in_gui(ev.mouse.x, ev.mouse.y) && moving_thing == INVALID && sec_mode != ESM_TEXTURE_VIEW && mode != EDITOR_MODE_OBJECTS ) { on_sector = get_sector(mouse_cursor_x, mouse_cursor_y, NULL, false); } else { on_sector = NULL; } //Move guide. if(sec_mode == ESM_GUIDE_MOUSE) { if(holding_m1) { guide_x += ev.mouse.dx / cam_zoom; guide_y += ev.mouse.dy / cam_zoom; } else if(holding_m2) { float new_w = guide_w + ev.mouse.dx / cam_zoom; float new_h = guide_h + ev.mouse.dy / cam_zoom; if(guide_aspect_ratio) { //Find the most significant change. if(ev.mouse.dx != 0 || ev.mouse.dy != 0) { bool most_is_width = fabs((double) ev.mouse.dx) > fabs((double) ev.mouse.dy); if(most_is_width) { float ratio = guide_h / guide_w; guide_w = new_w; guide_h = new_w * ratio; } else { float ratio = guide_w / guide_h; guide_h = new_h; guide_w = new_h * ratio; } } } else { guide_w = new_w; guide_h = new_h; } } guide_to_gui(); } else if(holding_m2) { //Move camera. cam_x += ev.mouse.dx / cam_zoom; cam_y += ev.mouse.dy / cam_zoom; } //Move thing. if(moving_thing != INVALID) { if(mode == EDITOR_MODE_SECTORS) { vertex* v_ptr = cur_area_data.vertexes[moving_thing]; v_ptr->x = snap_to_grid(mouse_cursor_x); v_ptr->y = snap_to_grid(mouse_cursor_y); } else if(mode == EDITOR_MODE_OBJECTS) { mob_gen* m_ptr = cur_area_data.mob_generators[moving_thing]; m_ptr->x = snap_to_grid(mouse_cursor_x); m_ptr->y = snap_to_grid(mouse_cursor_y); } else if(mode == EDITOR_MODE_PATHS) { path_stop* s_ptr = cur_area_data.path_stops[moving_thing]; s_ptr->x = snap_to_grid(mouse_cursor_x); s_ptr->y = snap_to_grid(mouse_cursor_y); s_ptr->calculate_dists(); path_preview_timeout.start(false); } else if(mode == EDITOR_MODE_SHADOWS) { tree_shadow* s_ptr = cur_area_data.tree_shadows[moving_thing]; s_ptr->x = snap_to_grid(mouse_cursor_x - moving_thing_x); s_ptr->y = snap_to_grid(mouse_cursor_y - moving_thing_y); shadow_to_gui(); } made_changes = true; } //Move path checkpoints. if(moving_path_preview_checkpoint != -1) { path_preview_checkpoints_x[moving_path_preview_checkpoint] = snap_to_grid(mouse_cursor_x); path_preview_checkpoints_y[moving_path_preview_checkpoint] = snap_to_grid(mouse_cursor_y); path_preview_timeout.start(false); } if(ev.mouse.dz != 0 && !is_mouse_in_gui(ev.mouse.x, ev.mouse.y)) { //Zoom. float new_zoom = cam_zoom + (cam_zoom * ev.mouse.dz * 0.1); new_zoom = max(ZOOM_MIN_LEVEL_EDITOR, new_zoom); new_zoom = min(ZOOM_MAX_LEVEL_EDITOR, new_zoom); float new_mc_x = ev.mouse.x / new_zoom - cam_x - (gui_x / 2 / new_zoom); float new_mc_y = ev.mouse.y / new_zoom - cam_y - (scr_h / 2 / new_zoom); cam_x -= (mouse_cursor_x - new_mc_x); cam_y -= (mouse_cursor_y - new_mc_y); mouse_cursor_x = new_mc_x; mouse_cursor_y = new_mc_y; cam_zoom = new_zoom; } if(sec_mode == ESM_NEW_SECTOR) { new_sector_valid_line = is_new_sector_line_valid( snap_to_grid(mouse_cursor_x), snap_to_grid(mouse_cursor_y) ); } } else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && !is_mouse_in_gui(ev.mouse.x, ev.mouse.y) ) { //Clicking. if(ev.mouse.button == 1) holding_m1 = true; else if(ev.mouse.button == 2) holding_m2 = true; else if(ev.mouse.button == 3) cam_zoom = 1.0; if(ev.mouse.button != 1) return; //If the user was editing, save it. if(mode == EDITOR_MODE_SECTORS) { gui_to_sector(); } else if(mode == EDITOR_MODE_OBJECTS) { gui_to_mob(); } else if(mode == EDITOR_MODE_SHADOWS) { gui_to_shadow(); } //Sector-related clicking. if(sec_mode == ESM_NONE && mode == EDITOR_MODE_SECTORS) { moving_thing = INVALID; edge* clicked_edge_ptr = NULL; size_t clicked_edge_nr = INVALID; bool created_vertex = false; for(size_t e = 0; e < cur_area_data.edges.size(); ++e) { edge* e_ptr = cur_area_data.edges[e]; if(!is_edge_valid(e_ptr)) continue; if( circle_intersects_line( mouse_cursor_x, mouse_cursor_y, 8 / cam_zoom, e_ptr->vertexes[0]->x, e_ptr->vertexes[0]->y, e_ptr->vertexes[1]->x, e_ptr->vertexes[1]->y ) ) { clicked_edge_ptr = e_ptr; clicked_edge_nr = e; break; } } if(double_click_time == 0) double_click_time = 0.5; else if(clicked_edge_ptr) { //Create a new vertex. double_click_time = 0; //New vertex, on the split point. //TODO create it on the edge, not on the cursor. vertex* new_v_ptr = new vertex(mouse_cursor_x, mouse_cursor_y); cur_area_data.vertexes.push_back(new_v_ptr); //New edge, copied from the original one. edge* new_e_ptr = new edge(*clicked_edge_ptr); cur_area_data.edges.push_back(new_e_ptr); //Save the original end vertex for later. vertex* end_v_ptr = clicked_edge_ptr->vertexes[1]; //Set vertexes on the new and original edges. new_e_ptr->vertex_nrs[0] = cur_area_data.vertexes.size() - 1; new_e_ptr->vertexes[0] = new_v_ptr; clicked_edge_ptr->vertex_nrs[1] = new_e_ptr->vertex_nrs[0]; clicked_edge_ptr->vertexes[1] = new_v_ptr; //Set sectors on the new edge. if(new_e_ptr->sectors[0]) { new_e_ptr->sectors[0]->edge_nrs.push_back( cur_area_data.edges.size() - 1 ); new_e_ptr->sectors[0]->edges.push_back(new_e_ptr); } if(new_e_ptr->sectors[1]) { new_e_ptr->sectors[1]->edge_nrs.push_back( cur_area_data.edges.size() - 1 ); new_e_ptr->sectors[1]->edges.push_back(new_e_ptr); } //Set edges of the new vertex. new_v_ptr->edge_nrs.push_back(cur_area_data.edges.size() - 1); new_v_ptr->edge_nrs.push_back(clicked_edge_nr); new_v_ptr->edges.push_back(new_e_ptr); new_v_ptr->edges.push_back(clicked_edge_ptr); //Update edge data on the end vertex of the original edge //(it now links to the new edge, not the old). for(size_t ve = 0; ve < end_v_ptr->edges.size(); ++ve) { if(end_v_ptr->edges[ve] == clicked_edge_ptr) { end_v_ptr->edges[ve] = new_e_ptr; end_v_ptr->edge_nrs[ve] = cur_area_data.edges.size() - 1; break; } } //Start dragging the new vertex. moving_thing = cur_area_data.vertexes.size() - 1; created_vertex = true; made_changes = true; } //Find a vertex to drag. if(!created_vertex) { for(size_t v = 0; v < cur_area_data.vertexes.size(); ++v) { if( dist( mouse_cursor_x, mouse_cursor_y, cur_area_data.vertexes[v]->x, cur_area_data.vertexes[v]->y ) <= 6.0 / cam_zoom ) { moving_thing = v; break; } } } //Find a sector to select. if(moving_thing == INVALID) { cur_sector = get_sector(mouse_cursor_x, mouse_cursor_y, NULL, false); sector_to_gui(); } } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_OBJECTS) { //Object-related clicking. cur_mob = NULL; moving_thing = INVALID; for(size_t m = 0; m < cur_area_data.mob_generators.size(); ++m) { mob_gen* m_ptr = cur_area_data.mob_generators[m]; float radius = m_ptr->type ? m_ptr->type->radius == 0 ? 16 : m_ptr->type->radius : 16; if( dist(m_ptr->x, m_ptr->y, mouse_cursor_x, mouse_cursor_y) <= radius ) { cur_mob = m_ptr; moving_thing = m; break; } } mob_to_gui(); } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_PATHS) { //Path-related clicking. cur_stop = NULL; moving_thing = INVALID; for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(s_ptr->x, s_ptr->y, mouse_cursor_x, mouse_cursor_y) <= STOP_RADIUS ) { cur_stop = s_ptr; moving_thing = s; break; } } moving_path_preview_checkpoint = -1; if(show_path_preview) { for(unsigned char c = 0; c < 2; ++c) { if( bbox_check( path_preview_checkpoints_x[c], path_preview_checkpoints_y[c], mouse_cursor_x, mouse_cursor_y, PATH_PREVIEW_CHECKPOINT_RADIUS / cam_zoom ) ) { moving_path_preview_checkpoint = c; break; } } } } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_SHADOWS) { //Shadow-related clicking. cur_shadow = NULL; moving_thing = INVALID; for(size_t s = 0; s < cur_area_data.tree_shadows.size(); ++s) { tree_shadow* s_ptr = cur_area_data.tree_shadows[s]; float min_x, min_y, max_x, max_y; get_shadow_bounding_box(s_ptr, &min_x, &min_y, &max_x, &max_y); if( mouse_cursor_x >= min_x && mouse_cursor_x <= max_x && mouse_cursor_y >= min_y && mouse_cursor_y <= max_y ) { cur_shadow = s_ptr; moving_thing = s; moving_thing_x = mouse_cursor_x - s_ptr->x; moving_thing_y = mouse_cursor_y - s_ptr->y; break; } } shadow_to_gui(); } if(sec_mode == ESM_NEW_SECTOR) { //Next vertex in a new sector. float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); new_sector_valid_line = is_new_sector_line_valid( snap_to_grid(mouse_cursor_x), snap_to_grid(mouse_cursor_y) ); if(new_sector_valid_line) { if( !new_sector_vertexes.empty() && dist( hotspot_x, hotspot_y, new_sector_vertexes[0]->x, new_sector_vertexes[0]->y ) <= VERTEX_MERGE_RADIUS ) { //Back to the first vertex. sec_mode = ESM_NONE; create_sector(); sector_to_gui(); made_changes = true; } else { //Add a new vertex. vertex* merge = get_merge_vertex( hotspot_x, hotspot_y, cur_area_data.vertexes, VERTEX_MERGE_RADIUS / cam_zoom ); if(merge) { new_sector_vertexes.push_back( new vertex(merge->x, merge->y) ); } else { new_sector_vertexes.push_back( new vertex(hotspot_x, hotspot_y) ); } } } } else if(sec_mode == ESM_NEW_OBJECT) { //Create a mob where the cursor is. sec_mode = ESM_NONE; float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); cur_area_data.mob_generators.push_back( new mob_gen(hotspot_x, hotspot_y) ); cur_mob = cur_area_data.mob_generators.back(); mob_to_gui(); made_changes = true; } else if(sec_mode == ESM_DUPLICATE_OBJECT) { //Duplicate the current mob to where the cursor is. sec_mode = ESM_NONE; if(cur_mob) { float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); mob_gen* new_mg = new mob_gen(*cur_mob); new_mg->x = hotspot_x; new_mg->y = hotspot_y; cur_area_data.mob_generators.push_back( new_mg ); cur_mob = new_mg; mob_to_gui(); made_changes = true; } } else if(sec_mode == ESM_NEW_STOP) { //Create a new stop where the cursor is. float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); cur_area_data.path_stops.push_back( new path_stop(hotspot_x, hotspot_y, vector<path_link>()) ); cur_stop = cur_area_data.path_stops.back(); made_changes = true; } else if (sec_mode == ESM_NEW_LINK1 || sec_mode == ESM_NEW_1WLINK1) { //Pick a stop to start the link on. for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <= STOP_RADIUS ) { new_link_first_stop = s_ptr; sec_mode = sec_mode == ESM_NEW_LINK1 ? ESM_NEW_LINK2 : ESM_NEW_1WLINK2; break; } } path_preview_timeout.start(false); made_changes = true; } else if (sec_mode == ESM_NEW_LINK2 || sec_mode == ESM_NEW_1WLINK2) { //Pick a stop to end the link on. for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <= STOP_RADIUS ) { if(new_link_first_stop == s_ptr) continue; //Check if these two stops already have a link. //Delete it if so. for( size_t l = 0; l < new_link_first_stop->links.size(); ++l ) { if(new_link_first_stop->links[l].end_ptr == s_ptr) { new_link_first_stop->links.erase( new_link_first_stop->links.begin() + l ); break; } } for(size_t l = 0; l < s_ptr->links.size(); ++l) { if(s_ptr->links[l].end_ptr == new_link_first_stop) { s_ptr->links.erase(s_ptr->links.begin() + l); break; } } new_link_first_stop->links.push_back( path_link(s_ptr, s) ); if(sec_mode == ESM_NEW_LINK2) { s_ptr->links.push_back( path_link(new_link_first_stop, INVALID) ); s_ptr->fix_nrs(cur_area_data); } new_link_first_stop->calculate_dists(); sec_mode = sec_mode == ESM_NEW_LINK2 ? ESM_NEW_LINK1 : ESM_NEW_1WLINK1; break; } } path_preview_timeout.start(false); made_changes = true; } else if(sec_mode == ESM_DEL_STOP) { //Pick a stop to delete. for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <= STOP_RADIUS ) { //Check all links to this stop. for( size_t s2 = 0; s2 < cur_area_data.path_stops.size(); ++s2 ) { path_stop* s2_ptr = cur_area_data.path_stops[s2]; for(size_t l = 0; l < s2_ptr->links.size(); ++l) { if(s2_ptr->links[l].end_ptr == s_ptr) { s2_ptr->links.erase(s2_ptr->links.begin() + l); break; } } } //Finally, delete the stop. delete s_ptr; cur_area_data.path_stops.erase( cur_area_data.path_stops.begin() + s ); break; } } for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { cur_area_data.path_stops[s]->fix_nrs(cur_area_data); } path_preview.clear(); path_preview_timeout.start(false); made_changes = true; } else if(sec_mode == ESM_DEL_LINK) { //Pick a link to delete. bool deleted = false; for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; for(size_t s2 = 0; s2 < s_ptr->links.size(); ++s2) { path_stop* s2_ptr = s_ptr->links[s2].end_ptr; if( circle_intersects_line( mouse_cursor_x, mouse_cursor_y, 8 / cam_zoom, s_ptr->x, s_ptr->y, s2_ptr->x, s2_ptr->y ) ) { s_ptr->links.erase(s_ptr->links.begin() + s2); for(size_t s3 = 0; s3 < s2_ptr->links.size(); ++s3) { if(s2_ptr->links[s3].end_ptr == s_ptr) { s2_ptr->links.erase( s2_ptr->links.begin() + s3 ); break; } } deleted = true; break; } } if(deleted) break; } path_preview.clear(); path_preview_timeout.start(false); made_changes = true; } else if(sec_mode == ESM_NEW_SHADOW) { //Create a new shadow where the cursor is. sec_mode = ESM_NONE; float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); tree_shadow* new_shadow = new tree_shadow(hotspot_x, hotspot_y); new_shadow->bitmap = bmp_error; cur_area_data.tree_shadows.push_back(new_shadow); cur_shadow = new_shadow; shadow_to_gui(); made_changes = true; } } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { //Mouse button release. if(ev.mouse.button == 1) holding_m1 = false; else if(ev.mouse.button == 2) holding_m2 = false; if( ev.mouse.button == 1 && mode == EDITOR_MODE_SECTORS && sec_mode == ESM_NONE && moving_thing != INVALID ) { //Release the vertex. vertex* moved_v_ptr = cur_area_data.vertexes[moving_thing]; vertex* final_vertex = moved_v_ptr; unordered_set<sector*> affected_sectors; //Check if we should merge. for(size_t v = 0; v < cur_area_data.vertexes.size(); ++v) { vertex* dest_v_ptr = cur_area_data.vertexes[v]; if(dest_v_ptr == moved_v_ptr) continue; if( dist( moved_v_ptr->x, moved_v_ptr->y, dest_v_ptr->x, dest_v_ptr->y ) <= (VERTEX_MERGE_RADIUS / cam_zoom) ) { merge_vertex( moved_v_ptr, dest_v_ptr, &affected_sectors ); final_vertex = dest_v_ptr; break; } } //Finally, re-triangulate the affected sectors. for(size_t e = 0; e < final_vertex->edges.size(); ++e) { edge* e_ptr = final_vertex->edges[e]; for(size_t s = 0; s < 2; ++s) { if(e_ptr->sectors[s]) { affected_sectors.insert(e_ptr->sectors[s]); } } } for( auto s = affected_sectors.begin(); s != affected_sectors.end(); ++s ) { if(!(*s)) continue; triangulate(*s); } //If somewhere along the line, the current sector //got marked for deletion, unselect it. if(cur_sector) { if(cur_sector->edges.empty()) { cur_sector = NULL; sector_to_gui(); } } //Check if the edge's vertexes intersect with any other edges. //If so, they're marked with red. check_edge_intersections(moved_v_ptr); moving_thing = INVALID; } else if( ev.mouse.button == 1 && sec_mode == ESM_NONE && moving_thing != INVALID ) { //Release thing. moving_thing = INVALID; } moving_path_preview_checkpoint = -1; } else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { //Key press. if( ev.keyboard.keycode == ALLEGRO_KEY_LSHIFT || ev.keyboard.keycode == ALLEGRO_KEY_RSHIFT ) { shift_pressed = true; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F1) { debug_edge_nrs = !debug_edge_nrs; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F2) { debug_sector_nrs = !debug_sector_nrs; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F3) { debug_vertex_nrs = !debug_vertex_nrs; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F4) { debug_triangulation = !debug_triangulation; } } else if(ev.type == ALLEGRO_EVENT_KEY_UP) { //Key release. if( ev.keyboard.keycode == ALLEGRO_KEY_LSHIFT || ev.keyboard.keycode == ALLEGRO_KEY_RSHIFT ) { shift_pressed = false; } } }
void extract_bad_sector_map(byte * buffer) { TRACE_FUN(8, "extract_bad_sector_map"); /* Fill the bad sector map with the contents of buffer. */ if (format_code == 4) { /* QIC-3010/3020 and wide QIC-80 tapes no longer have a failed * sector log but use this area to extend the bad sector map. */ memcpy(bad_sector_map, buffer + 256, sizeof(bad_sector_map)); } else { /* non-wide QIC-80 tapes have a failed sector log area that * mustn't be included in the bad sector map. */ memcpy(bad_sector_map, buffer + 256 + FAILED_SECTOR_LOG_SIZE, sizeof(bad_sector_map) - FAILED_SECTOR_LOG_SIZE); } #if 0 /* for testing of bad sector handling at end of tape */ ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 3] = 0x000003e0; ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 2] = 0xff3fffff; ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 1] = 0xffffe000; #endif #if 0 /* Enable to test bad sector handling */ ((unsigned long *) bad_sector_map)[30] = 0xfffffffe; ((unsigned long *) bad_sector_map)[32] = 0x7fffffff; ((unsigned long *) bad_sector_map)[34] = 0xfffeffff; ((unsigned long *) bad_sector_map)[36] = 0x55555555; ((unsigned long *) bad_sector_map)[38] = 0xffffffff; ((unsigned long *) bad_sector_map)[50] = 0xffff0000; ((unsigned long *) bad_sector_map)[51] = 0xffffffff; ((unsigned long *) bad_sector_map)[52] = 0xffffffff; ((unsigned long *) bad_sector_map)[53] = 0x0000ffff; #endif #if 0 /* Enable when testing multiple volume tar dumps. */ for (i = first_data_segment; i <= ftape_last_segment.id - 7; ++i) { ((unsigned long *) bad_sector_map)[i] = EMPTY_SEGMENT; } #endif #if 0 /* Enable when testing bit positions in *_error_map */ for (i = first_data_segment; i <= ftape_last_segment.id; ++i) { ((unsigned long *) bad_sector_map)[i] |= 0x00ff00ff; } #endif if (tracing > 2) { unsigned int map; int good_sectors = 0; int bad_sectors; unsigned int total_bad = 0; int i; if (format_code == 4 || format_code == 3) { byte *ptr = bad_sector_map; unsigned sector; do { sector = get_sector(&ptr, forward); if (sector != 0) { if (format_code == 4 && sector & 0x800000) { total_bad += SECTORS_PER_SEGMENT - 3; TRACEx1(6, "bad segment at sector: %6d", sector & 0x7fffff); } else { ++total_bad; TRACEx1(6, "bad sector: %6d", sector); } } } while (sector != 0); /* Display end-of-file marks */ do { sector = *((unsigned short *) ptr)++; if (sector) { TRACEx2(4, "eof mark: %4d/%2d", sector, *((unsigned short *) ptr)++); } } while (sector); } else { for (i = first_data_segment; i < segments_per_track * tracks_per_tape; ++i) { map = ((unsigned long *) bad_sector_map)[i]; bad_sectors = count_ones(map); if (bad_sectors > 0) { TRACEx2(6, "bsm for segment %4d: 0x%08x", i, map); if (bad_sectors > SECTORS_PER_SEGMENT - 3) { bad_sectors = SECTORS_PER_SEGMENT - 3; } total_bad += bad_sectors; } } } good_sectors = ((segments_per_track * tracks_per_tape - first_data_segment) * (SECTORS_PER_SEGMENT - 3)) - total_bad; TRACEx1(3, "%d Kb usable on this tape", good_sectors - ftape_last_segment.free); if (total_bad == 0) { TRACE(1, "WARNING: this tape has no bad blocks registered !"); } else { TRACEx1(2, "%d bad sectors", total_bad); } } TRACE_EXIT; }
void main(int argc, char **argv) { unsigned long countdown = 0; int wntDiskAdmin = 0; char char0 = 'a'; char defltr = 0; char force = 0; char const *dev_name; int fd_dev; if (argc < 2) { usage(); exit(1); } dev_name = argv[1]; fd_dev = open(dev_name, 0); if (fd_dev < 0) { perror(dev_name); exit(1); } get_sector(fd_dev, &dev_mbr, 0); uread(0, &new_mbr, 5, ".bin hdr"); /* discard header */ uread(0, &new_mbr, sizeof(new_mbr), "new mbr"); /* prototype mbr */ chk_magic(&new_mbr, "new mbr"); for ( (argv+=2), (argc-=2); argc > 0; (++argv), (--argc) ) if ('-'==**argv) { char *value = strchr(*argv, '='); if (0!=value) { *value++ = 0; } if (0==strcmp("-wait", *argv)) { if (0!=value) { countdown = atoi(value); if (0 < countdown && countdown < 4000) { countdown *= 1000000; } } } else if (0==strcmp("-char0", *argv)) { if (0!=value) { char0 = *value; } } else if (0==strcmp("-default", *argv)) { if (0!=value) { defltr = *value; } } else if (0==strcmp("-force", *argv)) { if (0!=value) { force = *value; } } else if (0==strcmp("-WNTDiskAdmin", *argv)) { wntDiskAdmin = 6; } else { fprintf(stderr,"ignoring option %s\n", *argv); } } else { break; } /* Somebody please tell me how to read an .obj symbol table so I can do these magic offsets symbolically! */ #define COUNT 0x184 #define DEFLTR 0x172 #define DESLTR 0x038 #define NAMES 0x19a memcpy(&new_mbr.random[COUNT -4], &countdown, sizeof(countdown)); memcpy(&new_mbr.random[DEFLTR -1], &defltr, sizeof(defltr)); memcpy(&new_mbr.random[DESLTR -2], &char0, sizeof(char0)); memcpy(&new_mbr.random[DESLTR -1], &force, sizeof(force)); if (0==countdown) {/* wait forever: no count at all */ new_mbr.random[COUNT -6] = 0xeb; /* JMP rel8 */ new_mbr.random[COUNT -5] = 0x0d; /* skip to getcWait */ } if (0 < argc) { char *labels = &new_mbr.random[NAMES]; int avail = (0x200 - 2 - 4*16 - wntDiskAdmin) - NAMES; qsort(argv, argc, sizeof(*argv), (qsort_fn_t)strcmp); for ( ; 0!=argc; ++argv, --argc ) { int const len = 1+strlen(2+*argv); if ((avail -= len) < 0) { fprintf(stderr,"Use shorter labels; " "`%c=%s' won't fit.\n", **argv, 2+*argv); } else { strcpy(labels, 2+*argv); labels += len; } if (1 < argc /* not last */ && (1 + *argv[0]) != *argv[1] ) { fprintf(stderr, "letters must be consecutive: %s %s\n", argv[0], argv[1] ); exit(1); } } fprintf(stderr, "%d bytes available.\n", avail); } if (0!=wntDiskAdmin) { /* WindowsNT disk administrator uses these 6 bytes */ memcpy(&new_mbr.random[446-6], &dev_mbr.random[446-6], 6); } memcpy(&new_mbr.part[0], &dev_mbr.part[0], 4*16); uwrite(1, &new_mbr, sizeof(new_mbr), "stdout"); exit(0); }
/* * read_extended_partition -- * recursively reads extended partition sector from the device * and constructs the partition table tree * * PARAMETERS: * fd - file descriptor * start - start sector of primary extended partition, used for * calculation of absolute partition sector address * ext_part - description of extended partition to process * * RETURNS: * RTEMS_SUCCESSFUL if success, * RTEMS_NO_MEMOTY if cannot allocate memory for part_desc_t strucure, * RTEMS_INTERNAL_ERROR if other error occurs. */ static rtems_status_code read_extended_partition(int fd, uint32_t start, rtems_part_desc_t *ext_part) { int i; rtems_sector_data_t *sector = NULL; uint32_t here; uint8_t *data; rtems_part_desc_t *new_part_desc; rtems_status_code rc; if ((ext_part == NULL) || (ext_part->disk_desc == NULL)) { return RTEMS_INTERNAL_ERROR; } /* get start sector of current extended partition */ here = ext_part->start; /* get first extended partition sector */ rc = get_sector(fd, here, §or); if (rc != RTEMS_SUCCESSFUL) { if (sector) free(sector); return rc; } if (!msdos_signature_check(sector)) { free(sector); return RTEMS_INTERNAL_ERROR; } /* read and process up to 4 logical partition descriptors */ data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET; for (i = 0; i < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; i++) { /* if data_to_part_desc fails skip this partition * and parse the next one */ rc = data_to_part_desc(data, &new_part_desc); if (rc != RTEMS_SUCCESSFUL) { free(sector); return rc; } if (new_part_desc == NULL) { data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE; continue; } ext_part->sub_part[i] = new_part_desc; new_part_desc->ext_part = ext_part; new_part_desc->disk_desc = ext_part->disk_desc; if (is_extended(new_part_desc->sys_type)) { new_part_desc->log_id = EMPTY_PARTITION; new_part_desc->start += start; read_extended_partition(fd, start, new_part_desc); } else { rtems_disk_desc_t *disk_desc = new_part_desc->disk_desc; disk_desc->partitions[disk_desc->last_log_id] = new_part_desc; new_part_desc->log_id = ++disk_desc->last_log_id; new_part_desc->start += here; new_part_desc->end = new_part_desc->start + new_part_desc->size - 1; } data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE; } free(sector); return RTEMS_SUCCESSFUL; }
/* * read_mbr -- * reads Master Boot Record (sector 0) of physical device and * constructs disk description structure * * PARAMETERS: * disk_desc - returned disc description structure * * RETURNS: * RTEMS_SUCCESSFUL if success, * RTEMS_INTERNAL_ERROR otherwise */ static rtems_status_code read_mbr(int fd, rtems_disk_desc_t *disk_desc) { int part_num; rtems_sector_data_t *sector = NULL; rtems_part_desc_t *part_desc; uint8_t *data; rtems_status_code rc; /* get MBR sector */ rc = get_sector(fd, 0, §or); if (rc != RTEMS_SUCCESSFUL) { if (sector) free(sector); return rc; } /* check if the partition table structure is MS-DOS style */ if (!msdos_signature_check(sector)) { free(sector); return RTEMS_INTERNAL_ERROR; } /* read and process 4 primary partition descriptors */ data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET; for (part_num = 0; part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; part_num++) { rc = data_to_part_desc(data, &part_desc); if (rc != RTEMS_SUCCESSFUL) { free(sector); return rc; } if (part_desc != NULL) { part_desc->log_id = part_num + 1; part_desc->disk_desc = disk_desc; part_desc->end = part_desc->start + part_desc->size - 1; disk_desc->partitions[part_num] = part_desc; } else { disk_desc->partitions[part_num] = NULL; } data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE; } free(sector); disk_desc->last_log_id = RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; /* There cannot be more than one extended partition, but we are to process each primary partition */ for (part_num = 0; part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; part_num++) { part_desc = disk_desc->partitions[part_num]; if (part_desc != NULL && is_extended(part_desc->sys_type)) { read_extended_partition(fd, part_desc->start, part_desc); free(part_desc); disk_desc->partitions[part_num] = NULL; } } return RTEMS_SUCCESSFUL; }
void exec_image(char *image) /* Get a Minix image into core, patch it up and execute. */ { int i; struct image_header hdr; char *buf; u32_t vsec, addr, limit, aout, n, totalmem = 0; struct process *procp; /* Process under construction. */ long a_text, a_data, a_bss, a_stack; int banner= 0; long processor= a2l(b_value("processor")); u16_t kmagic, mode; char *console; char params[SECTOR_SIZE]; extern char *sbrk(int); char *verb; /* The stack is pretty deep here, so check if heap and stack collide. */ (void) sbrk(0); if ((verb= b_value(VERBOSEBOOTVARNAME)) != nil) verboseboot = a2l(verb); printf("\nLoading "); pretty_image(image); printf(".\n"); vsec= 0; /* Load this sector from image next. */ addr= mem[0].base; /* Into this memory block. */ limit= mem[0].base + mem[0].size; if (limit > caddr) limit= caddr; /* Allocate and clear the area where the headers will be placed. */ aout = (limit -= PROCESS_MAX * A_MINHDR); /* Clear the area where the headers will be placed. */ raw_clear(aout, PROCESS_MAX * A_MINHDR); /* Read the many different processes: */ for (i= 0; vsec < image_size; i++) { u32_t startaddr; startaddr = addr; if (i == PROCESS_MAX) { printf("There are more then %d programs in %s\n", PROCESS_MAX, image); errno= 0; return; } procp= &process[i]; /* Read header. */ DEBUGEXTRA(("Reading header... ")); for (;;) { if ((buf= get_sector(vsec++)) == nil) return; memcpy(&hdr, buf, sizeof(hdr)); if (BADMAG(hdr.process)) { errno= ENOEXEC; return; } /* Check the optional label on the process. */ if (selected(hdr.name)) break; /* Bad label, skip this process. */ vsec+= proc_size(&hdr); } DEBUGEXTRA(("done\n")); /* Sanity check: an 8086 can't run a 386 kernel. */ if (hdr.process.a_cpu == A_I80386 && processor < 386) { printf("You can't run a 386 kernel on this 80%ld\n", processor); errno= 0; return; } /* Get the click shift from the kernel text segment. */ if (i == KERNEL_IDX) { if (!get_clickshift(vsec, &hdr)) return; addr= align(addr, click_size); /* big kernels must be loaded into extended memory */ if (k_flags & K_KHIGH) { addr= mem[1].base; limit= mem[1].base + mem[1].size; } } /* Save a copy of the header for the kernel, with a_syms * misused as the address where the process is loaded at. */ DEBUGEXTRA(("raw_copy(0x%x, 0x%lx, 0x%x)... ", aout + i * A_MINHDR, mon2abs(&hdr.process), A_MINHDR)); hdr.process.a_syms= addr; raw_copy(aout + i * A_MINHDR, mon2abs(&hdr.process), A_MINHDR); DEBUGEXTRA(("done\n")); if (!banner) { DEBUGBASIC((" cs ds text data bss")); if (k_flags & K_CHMEM) DEBUGBASIC((" stack")); DEBUGBASIC(("\n")); banner= 1; } /* Segment sizes. */ DEBUGEXTRA(("a_text=0x%lx; a_data=0x%lx; a_bss=0x%lx; a_flags=0x%x)\n", hdr.process.a_text, hdr.process.a_data, hdr.process.a_bss, hdr.process.a_flags)); a_text= hdr.process.a_text; a_data= hdr.process.a_data; a_bss= hdr.process.a_bss; if (k_flags & K_CHMEM) { a_stack= hdr.process.a_total - a_data - a_bss; if (!(hdr.process.a_flags & A_SEP)) a_stack-= a_text; } else { a_stack= 0; } /* Collect info about the process to be. */ procp->cs= addr; /* Process may be page aligned so that the text segment contains * the header, or have an unmapped zero page against vaxisms. */ procp->entry= hdr.process.a_entry; if (hdr.process.a_flags & A_PAL) a_text+= hdr.process.a_hdrlen; if (hdr.process.a_flags & A_UZP) procp->cs-= click_size; /* Separate I&D: two segments. Common I&D: only one. */ if (hdr.process.a_flags & A_SEP) { /* Read the text segment. */ DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", vsec, a_text, addr, limit)); if (!get_segment(&vsec, &a_text, &addr, limit)) return; DEBUGEXTRA(("get_segment done vsec=0x%lx a_text=0x%lx " "addr=0x%lx\n", vsec, a_text, addr)); /* The data segment follows. */ procp->ds= addr; if (hdr.process.a_flags & A_UZP) procp->ds-= click_size; procp->data= addr; } else { /* Add text to data to form one segment. */ procp->data= addr + a_text; procp->ds= procp->cs; a_data+= a_text; } /* Read the data segment. */ DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", vsec, a_data, addr, limit)); if (!get_segment(&vsec, &a_data, &addr, limit)) return; DEBUGEXTRA(("get_segment done vsec=0x%lx a_data=0x%lx " "addr=0x%lx\n", vsec, a_data, addr)); /* Make space for bss and stack unless... */ if (i != KERNEL_IDX && (k_flags & K_CLAIM)) a_bss= a_stack= 0; DEBUGBASIC(("%07lx %07lx %8ld %8ld %8ld", procp->cs, procp->ds, hdr.process.a_text, hdr.process.a_data, hdr.process.a_bss)); if (k_flags & K_CHMEM) DEBUGBASIC((" %8ld", a_stack)); /* Note that a_data may be negative now, but we can look at it * as -a_data bss bytes. */ /* Compute the number of bss clicks left. */ a_bss+= a_data; n= align(a_bss, click_size); a_bss-= n; /* Zero out bss. */ DEBUGEXTRA(("\nraw_clear(0x%lx, 0x%lx); limit=0x%lx... ", addr, n, limit)); if (addr + n > limit) { errno= ENOMEM; return; } raw_clear(addr, n); DEBUGEXTRA(("done\n")); addr+= n; /* And the number of stack clicks. */ a_stack+= a_bss; n= align(a_stack, click_size); a_stack-= n; /* Add space for the stack. */ addr+= n; /* Process endpoint. */ procp->end= addr; if (verboseboot >= VERBOSEBOOT_BASIC) printf(" %s\n", hdr.name); else { u32_t mem; mem = addr-startaddr; printf("%s ", hdr.name); totalmem += mem; } if (i == 0 && (k_flags & (K_HIGH | K_KHIGH)) == K_HIGH) { /* Load the rest in extended memory. */ addr= mem[1].base; limit= mem[1].base + mem[1].size; } } if (verboseboot < VERBOSEBOOT_BASIC) printf("(%dk)\n", totalmem/1024); if ((n_procs= i) == 0) { printf("There are no programs in %s\n", image); errno= 0; return; } /* Check the kernel magic number. */ raw_copy(mon2abs(&kmagic), process[KERNEL_IDX].data + MAGIC_OFF, sizeof(kmagic)); if (kmagic != KERNEL_D_MAGIC) { printf("Kernel magic number is incorrect (0x%x@0x%lx)\n", kmagic, process[KERNEL_IDX].data + MAGIC_OFF); errno= 0; return; } /* Patch sizes, etc. into kernel data. */ DEBUGEXTRA(("patch_sizes()... ")); patch_sizes(); DEBUGEXTRA(("done\n")); #if !DOS if (!(k_flags & K_MEML)) { /* Copy the a.out headers to the old place. */ raw_copy(HEADERPOS, aout, PROCESS_MAX * A_MINHDR); } #endif /* Run the trailer function just before starting Minix. */ DEBUGEXTRA(("run_trailer()... ")); if (!run_trailer()) { errno= 0; return; } DEBUGEXTRA(("done\n")); /* Translate the boot parameters to what Minix likes best. */ DEBUGEXTRA(("params2params(0x%x, 0x%x)... ", params, sizeof(params))); if (!params2params(params, sizeof(params))) { errno= 0; return; } DEBUGEXTRA(("done\n")); /* Set the video to the required mode. */ if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) { mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE : MONO_MODE; } DEBUGEXTRA(("set_mode(%d)... ", mode)); set_mode(mode); DEBUGEXTRA(("done\n")); /* Close the disk. */ DEBUGEXTRA(("dev_close()... ")); (void) dev_close(); DEBUGEXTRA(("done\n")); /* Minix. */ DEBUGEXTRA(("minix(0x%lx, 0x%lx, 0x%lx, 0x%x, 0x%x, 0x%lx)\n", process[KERNEL_IDX].entry, process[KERNEL_IDX].cs, process[KERNEL_IDX].ds, params, sizeof(params), aout)); minix(process[KERNEL_IDX].entry, process[KERNEL_IDX].cs, process[KERNEL_IDX].ds, params, sizeof(params), aout); if (!(k_flags & K_BRET)) { extern u32_t reboot_code; raw_copy(mon2abs(params), reboot_code, sizeof(params)); } parse_code(params); /* Return from Minix. Things may have changed, so assume nothing. */ fsok= -1; errno= 0; /* Read leftover character, if any. */ scan_keyboard(); /* Restore screen contents. */ restore_screen(); }
long rwrite(Rfile tpf, void *buf, long count) /* Write a buffer to an open ram-disk file. */ { char ***platter; char **track; char *data; int i; int ssize, so; int flags; long filept; long written; long new_size; flags = tpf->flags; if (!(flags&TF_OPEN)) { rerr = Err_file_not_open; return(0); } if (!(flags&TF_WRITE)) { rerr = Err_write; return(0); } if (count <= 0) return(0); data = buf; written = 0; filept = tpf->filep; new_size = filept + count; platter = tpf->platters + get_platter(filept); for (;;) { if ((track = *platter) == NULL) if ((*platter = track = tget_clear()) == NULL) goto OUT; i = get_track(filept); track += i; for ( ; i< TRD_TRACK; i++) { if (*track == NULL) if ((*track = tget_sector()) == NULL) goto OUT; so = get_sector(filept); ssize = TRD_SECTOR - so; if (count > ssize) { memcpy(*track + so, data, ssize); written += ssize; data += ssize; count -= ssize; filept += ssize; } else { memcpy(*track + so, data, (size_t)count); written += count; filept += count; goto OUT; } track++; } platter++; } OUT: if (tpf->size < (tpf->filep = filept)) tpf->size = filept; return(written); }