/* Scan /proc/devices for a blockdevice (BLOCKDEV is 1) or a character * device (BLOCKDEV is 0) with a major number matching the major number of DEV. * When there is a match, store entry data in ENTRY and return 0. Return * non-zero otherwise. */ int proc_dev_get_entry(dev_t device, int blockdev, struct proc_dev_entry* entry) { struct file_buffer file; int rc; int scan_blockdev = 0; rc = get_file_buffer(&file, proc_dev_filename); if (rc) return rc; rc = -1; while (!eof(&file)) { if (scan_string(&file, "Block") == 0) { skip_line(&file); scan_blockdev = 1; continue; } else if (scan_dev_entry(&file, entry, scan_blockdev) == 0) { if ((major(entry->device) == major(device)) && blockdev == scan_blockdev) { rc = 0; break; } proc_dev_free_entry(entry); } else skip_line(&file); } free_file_buffer(&file); return rc; }
int main(int argc, char *argv[]) { int fd; char name[64], *buf, *out = NULL, *verify; size_t len, outlen; buf = get_file_buffer(argv[1], &len); if (buf) { if (argc > 2) { if (url_unescape(buf, len, &out, &outlen) == 0) { printf("%.*s\n", (int)outlen, out); if ((verify = url_escape(out, outlen))) { fd = get_tmpfile(name, 0666, NULL, NULL); if (fd > 0) { printf("verify file:%s\n", name); write(fd, verify, strlen(verify)); close(fd); } } } } else { if ((out = url_escape(buf, len))) printf("%s\n", out); } free(buf); if (out) free(out); } }
Object* native_file_eof(Object *cxt, Object *frame, Object *self) { Object *stack = get(cxt, frame, "stack"); FileBuffer *file_buf = get_file_buffer(self); if ( file_buf == 0 ) { return new_exception(cxt, frame, "Expected a file as first argument"); } if ( feof(file_buf->file) ) { push(cxt, stack, get_true(cxt)); } else { push(cxt, stack, get_false(cxt)); } return frame; };
Object* native_file_close(Object *cxt, Object *frame, Object *self) { FileBuffer *file_buf = get_file_buffer(self); if ( file_buf == 0 ) { return new_exception(cxt, frame, "Expected a file as first argument"); } if ( file_buf->file == 0 ) { return new_exception(cxt, frame, "File pointer is null"); } int result = fclose(file_buf->file); if ( result != 0 ) { return new_errno_exception(cxt, frame, "Failed while closing file"); } return frame; }
static int set_b2l_file(lua_State *L) { size_t blob_size; uint8_t *blob = get_file_buffer(lua_tostring(L, -1), &blob_size); if (blob == NULL) { printf("failed to load blob file %s\n",lua_tostring(L, -1)); return -1; } g_gl_state.blob = blob; g_gl_state.blob_size = blob_size; g_gl_state.blob_updated = true; g_gl_state.fragment_shader_text = NULL; g_gl_state.vertex_shader_text = NULL; g_gl_state.program_valid = false; return 0; }
Object* native_file_read_into_offset_length(Object *cxt, Object *frame, Object *self) { Object *stack = get_stack(cxt, frame); FileBuffer *file_buf = get_file_buffer(self); Object *length_obj = pop(cxt, stack); Object *offset_obj = pop(cxt, stack); Object *char_array = pop(cxt, stack); if ( file_buf == 0 ) { return new_exception(cxt, frame, "Expected a file as self argument"); } CharArrayBuffer *char_array_buf = get_char_array_buffer(char_array); if ( char_array_buf == 0 ) { return new_exception(cxt, frame, "Expected a char_array as first argument"); } if ( ! is_boxed_int(cxt, offset_obj) ) { return new_exception(cxt, frame, "Expected a boxed int as second argument"); } Fixnum offset = boxed_int_to_fixnum(cxt, offset_obj); if ( ! is_boxed_int(cxt, length_obj) ) { return new_exception(cxt, frame, "Expected a fixnum as third argument"); } Fixnum length = boxed_int_to_fixnum(cxt, length_obj); if ( offset + length > char_array_buf->reserved ) { return new_exception(cxt, frame, "Offset + length exceeds char_array length"); } int num_read = fread(char_array_buf->data + offset, 1, length, file_buf->file); if ( num_read >= 0 ) { char_array_truncate_buffer(cxt, char_array, offset + num_read); return frame; } else { return new_errno_exception(cxt, frame, "Unable to read from file"); } }
shared_ptr<FileBuffer> Fat::get_file_buff(string filename) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err = "Can't find file "; err += filename; set_last_err_string(err); return NULL; } shared_ptr<FileBuffer> pbuff = get_file_buffer(m_filename); shared_ptr<FileBuffer> p(new FileBuffer); size_t filesize = m_filemap[filename].file_size; p->resize(filesize); int cur = m_filemap[filename].start_cluster; size_t off; for (off = 0; off < filesize; off += m_cluster) { size_t sz; sz = filesize - off; if (sz > m_cluster) sz = m_cluster; if (cur == 0xFFFF) { set_last_err_string("Early finished at fat"); return NULL; } void *pcluster = get_data_buff(pbuff, cur); memcpy(p->data() + off, pcluster, sz); cur = get_next_cluster(pbuff, cur); } return p; }
/* Scan /proc/partitions for an entry matching DEVICE. When there is a match, * store entry data in ENTRY and return 0. Return non-zero otherwise. */ int proc_part_get_entry(dev_t device, struct proc_part_entry* entry) { struct file_buffer file; int rc; rc = get_file_buffer(&file, proc_part_filename); if (rc) return rc; rc = -1; while (!eof(&file)) { if (scan_part_entry(&file, entry) == 0) { if (entry->device == device) { rc = 0; break; } proc_part_free_entry(entry); } else skip_line(&file); } free_file_buffer(&file); return rc; }
Fixnum is_file(Object *cxt, Object *obj) { return get_file_buffer(obj) != 0; }
void load_rom(char const *filename, bool print_info) { #define PRINT_INFO(...) do { if (print_info) printf(__VA_ARGS__); } while(0) size_t rom_buf_size; rom_buf = get_file_buffer(filename, rom_buf_size); // // Parse header // is_pal = strstr(filename, "(E)") || strstr(filename, "PAL"); PRINT_INFO("guessing %s based on filename\n", is_pal ? "PAL" : "NTSC"); fail_if(rom_buf_size < 16, "'%s' is too short to be a valid iNES file (is %zu bytes - not even enough to hold the 16-byte " "header)", filename, rom_buf_size); fail_if(!MEM_EQ(rom_buf, "NES\x1A"), "'%s' does not start with the expected byte sequence 'N', 'E', 'S', 0x1A", filename); prg_16k_banks = rom_buf[4]; chr_8k_banks = rom_buf[5]; PRINT_INFO("PRG ROM size: %u KB\nCHR ROM size: %u KB\n", 16*prg_16k_banks, 8*chr_8k_banks); fail_if(prg_16k_banks == 0, // TODO: This makes sense for NES 2.0 "the iNES header specifies zero banks of PRG ROM (program storage), which makes no sense"); fail_if(!is_pow_2_or_0(prg_16k_banks) || !is_pow_2_or_0(chr_8k_banks), "non-power-of-two PRG and CHR sizes are not supported yet"); size_t const min_size = 16 + 512*has_trainer + 0x4000*prg_16k_banks + 0x2000*chr_8k_banks; fail_if(rom_buf_size < min_size, "'%s' is too short to hold the specified amount of PRG (program data) and CHR (graphics data) " "ROM - is %zu bytes, expected at least %zu bytes (16 (header) + %s%u*16384 (PRG) + %u*8192 (CHR))", filename, rom_buf_size, min_size, has_trainer ? "512 (trainer) + " : "", prg_16k_banks, chr_8k_banks); unsigned mapper; // Possibly updated with the high nibble below mapper = rom_buf[6] >> 4; bool const is_nes_2_0 = (rom_buf[7] & 0x0C) == 0x08; PRINT_INFO(is_nes_2_0 ? "in NES 2.0 format\n" : "in iNES format\n"); // Assume we're dealing with a corrupted header (e.g. one containing // "DiskDude!" in bytes 7-15) if the ROM is not in NES 2.0 format and bytes // 12-15 are not all zero if (!is_nes_2_0 && !MEM_EQ(rom_buf + 12, "\0\0\0\0")) PRINT_INFO("header looks corrupted (bytes 12-15 not all zero) - ignoring byte 7\n"); else { is_vs_unisystem = rom_buf[7] & 1; is_playchoice_10 = rom_buf[7] & 2; mapper |= (rom_buf[7] & 0xF0); } PRINT_INFO("mapper: %u\n", mapper); if (rom_buf[6] & 8) // The cart contains 2 KB of additional CIRAM (nametable memory) and uses // four-screen (linear) addressing mirroring = FOUR_SCREEN; else mirroring = rom_buf[6] & 1 ? VERTICAL : HORIZONTAL; if ((has_battery = rom_buf[6] & 2)) PRINT_INFO("has battery\n"); if ((has_trainer = rom_buf[6] & 4)) PRINT_INFO("has trainer\n"); // // Set pointers, allocate memory areas, and do misc. setup // prg_base = rom_buf + 16 + 512*has_trainer; // Default has_bus_conflicts = false; do_rom_specific_overrides(); // Needs to come after a possible override prerender_line = is_pal ? 311 : 261; PRINT_INFO("mirroring: %s\n", mirroring_to_str[mirroring]); fail_if(!(ciram = alloc_array_init<uint8_t>(mirroring == FOUR_SCREEN ? 0x1000 : 0x800, 0xFF)), "failed to allocate %u bytes of nametable memory", mirroring == FOUR_SCREEN ? 0x1000 : 0x800); if (mirroring == FOUR_SCREEN || mapper == 7) // Assume no WRAM when four-screen, per // http://wiki.nesdev.com/w/index.php/INES_Mapper_004. Also assume no // WRAM for AxROM (mapper 7) as having it breaks Battletoads & Double // Dragon. No AxROM games use WRAM. wram_base = wram_6000_page = NULL; else { // iNES assumes all carts have 8 KB of WRAM. For MMC5, assume the cart // has 64 KB. wram_8k_banks = (mapper == 5) ? 8 : 1; fail_if(!(wram_6000_page = wram_base = alloc_array_init<uint8_t>(0x2000*wram_8k_banks, 0xFF)), "failed to allocate %u KB of WRAM", 8*wram_8k_banks); } if ((chr_is_ram = (chr_8k_banks == 0))) { // Assume cart has 8 KB of CHR RAM, except for Videomation which has 16 KB chr_8k_banks = (mapper == 13) ? 2 : 1; fail_if(!(chr_base = alloc_array_init<uint8_t>(0x2000*chr_8k_banks, 0xFF)), "failed to allocate %u KB of CHR RAM", 8*chr_8k_banks); } else chr_base = prg_base + 16*1024*prg_16k_banks; #undef PRINT_INFO fail_if(is_nes_2_0, "NES 2.0 not yet supported"); fail_if(!mapper_fns_table[mapper].init, "mapper %u not supported\n", mapper); mapper_fns = mapper_fns_table[mapper]; mapper_fns.init(); // Needs to come first, as it sets NTSC/PAL timing parameters used by some // of the other initialization functions init_timing_for_rom(); init_apu_for_rom(); init_audio_for_rom(); init_ppu_for_rom(); init_save_states_for_rom(); #ifdef RECORD_MOVIE // Needs to know whether PAL or NTSC, so can't be done in main() init_movie(); #endif }
bool check_file_exist(string filename, bool start_async_load) { return get_file_buffer(filename, true) != NULL; }
shared_ptr<FileBuffer> get_file_buffer(string filename) { return get_file_buffer(filename, false); }
int bz_async_load(string filename, FileBuffer *p) { shared_ptr<FileBuffer> pbz; pbz = get_file_buffer(filename); if (pbz == NULL) { string err; err = "Failure get file buffer: "; err += filename; set_last_err_string(err); return -1; } vector<bz2_blk> blk; bz2_blk one; memset(&one, 0, sizeof(one)); blk.push_back(one); size_t total = 0; uint8_t *p1 = &pbz->at(0); for (size_t i = 0; i < pbz->size() - 10; i++) { uint16_t *header = (uint16_t *)p1++; if (*header == 0x5a42) //"BZ" { uint32_t *magic1 = (uint32_t *)&pbz->at(i+4); if (*magic1 == 0x26594131) //PI 3.1415926 { uint16_t *magic2 = (uint16_t *)&pbz->at(i + 8); if (*magic2 == 0x5953) { /*which is valude bz2 header*/ struct bz2_blk one; one.start = i; blk[blk.size() - 1].size = i - blk[blk.size() - 1].start; one.decompress_offset = blk[blk.size() - 1].decompress_offset + blk[blk.size() - 1].decompress_size; one.decompress_size = (pbz->at(i + 3) - '0') * 100 * 1000; /* not l024 for bz2 */ blk.push_back(one); total += one.decompress_size; } } } } if (blk.size() == 1) { set_last_err_string("Can't find validate bz2 magic number"); return -1; } blk[blk.size() - 1].size = pbz->size() - blk[blk.size() - 1].start; int nthread = thread::hardware_concurrency(); vector<thread> threads; p->resize(total); for (int i = 0; i < nthread; i++) { threads.push_back(thread(bz2_decompress, pbz, p, &blk, i, nthread)); } for (int i = 0; i < nthread; i++) { threads[i].join(); } for (int i = 1; i < blk.size(); i++) { if (blk[i].error) { set_last_err_string("decompress err"); return -1; } if ((blk[i].decompress_size != blk[i].actual_size) && (i != blk.size() - 1)) { set_last_err_string("bz2: only support last block less then other block"); return -1; } } size_t sz = blk[blk.size() - 1].decompress_size - blk[blk.size() - 1].actual_size; p->resize(total - sz); p->m_loaded = true; return 0; }
int Fat::Open(string filename) { m_filename = filename; shared_ptr<FileBuffer> pbuff = get_file_buffer(m_filename); if (pbuff == NULL) return -1; if (pbuff->size() < 512) { set_last_err_string("File too small"); return -1; } if (pbuff->at(510) != 0x55|| pbuff->at(511) != 0xAA) { set_last_err_string("Partition signature miss matched"); return -1; } Partition *pPart = (Partition *)(pbuff->data() + 446); m_fat_part_start = pPart->lba_start * 512; uint8_t *boot = pbuff->data() + m_fat_part_start; if (boot[510] != 0x55 || boot[511] != 0xAA) { set_last_err_string("Boot Sector signature miss matched"); return -1; } m_logical_sector_perfat = boot[0x16]; m_logical_sector_perfat += boot[0x17] << 8; if (m_logical_sector_perfat == 0) { m_logical_sector_perfat = boot[0x24]; m_logical_sector_perfat += boot[0x25] << 8; m_logical_sector_perfat += boot[0x26] << 16; m_logical_sector_perfat += boot[0x27] << 24; } m_fat_table_offset = boot[0xE]; m_fat_table_offset += boot[0xF] << 8; m_fat_table_offset *= 512; m_cluster = boot[0xD]; m_cluster *= 512; int num_of_fat = boot[0x10]; m_root_dir_offset = m_logical_sector_perfat * 512 * num_of_fat + m_fat_table_offset; m_num_of_rootdir = boot[0x11]; m_num_of_rootdir = boot[0x12] << 8; FatDirEntry *entry; entry = (FatDirEntry*)(boot + m_root_dir_offset); m_filemap.clear(); for (int i = 0; i < m_num_of_rootdir; i++) { string filename; if (entry->attr == 0x8) entry++; if (entry->filename[0] == 0) break; filename.clear(); while (entry->attr == 0xF) { filename.insert(0, lfn2string((FatLFN *)entry)); entry++; } if (filename.empty()) { filename.append((char*)entry->filename, 8); if (entry->ext[0]) { filename.append("."); filename.append((char*)entry->ext, 3); } } m_filemap[filename] = *entry; entry++; if (entry->filename[0] == 0) break; } return 0; }