Created
March 3, 2013 06:26
-
-
Save Blecki/5074959 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Functions for reading directories on a bsf512 formatted disc | |
| #ifndef DCPUB_LIB_BFS512_DIRECTORIES | |
| #define DCPUB_LIB_BFS512_DIRECTORIES | |
| #include m35fd.dc | |
| #include bfs512.dc | |
| #include bfs512_files.dc | |
| #include vec.dc | |
| #define BFS512_DE_DIRECTORY 0 | |
| #define BFS512_DE_FILE 1 | |
| struct bfs512_DIRECTORY_ENTRY | |
| { | |
| type; | |
| sector; | |
| name[8]; | |
| } | |
| struct bfs512_DIRECTORY_HEADER | |
| { | |
| version; | |
| child_count; | |
| } | |
| struct bfs512_OPEN_DIRECTORY | |
| { | |
| children_left; | |
| file:bfs512_FILE[sizeof(bfs512_FILE)]; | |
| } | |
| //Given a string of up to 16 characters and a buffer of exactly 8 words, pack the string into the buffer. | |
| function bfs512_pack_filename(filename, into) | |
| { | |
| local fi = 0; | |
| local ii = 0; | |
| local fl = veclen(filename); | |
| while (fi < fl) | |
| { | |
| local word = (filename[fi + 1] & 0x00FF) << 8; | |
| if ((fi + 1) < fl) word += filename[fi + 2] & 0x00FF; | |
| into[ii] = word; | |
| fi += 2; | |
| ii += 1; | |
| } | |
| while (ii < 8) | |
| { | |
| into[ii] = 0x0000; | |
| ii += 1; | |
| } | |
| } | |
| //Compare two packed filenames. | |
| function bfs512_compare_filenames(d, f) | |
| { | |
| local i = 0; | |
| while (i < 8) | |
| { | |
| if (d[i] != d[i]) return 0; | |
| i += 1; | |
| } | |
| return 1; | |
| } | |
| //Open a directory so that entrys can be read. | |
| function bfs512_open_directory(file_system:bfs512_SYSTEM_HEADER, drive, sector, out:bfs512_OPEN_DIRECTORY) | |
| { | |
| local err = bfs512_open_read(out.file, file_system, drive, sector); | |
| if (err != BFS512_ERR_NONE) return err; | |
| local header:bfs512_DIRECTORY_HEADER[sizeof(bfs512_DIRECTORY_HEADER)]; | |
| bfs512_read(out.file, header, sizeof(bfs512_DIRECTORY_HEADER)); | |
| out.children_left = header.child_count; | |
| return BFS512_ERR_NONE; | |
| } | |
| //Read the next directory entry in the directory. | |
| function bfs512_read_directory_entry(directory:bfs512_OPEN_DIRECTORY, out:bfs512_DIRECTORY_ENTRY) | |
| { | |
| if (directory.children_left == 0) return BFS512_ERR_EOF; | |
| return bfs512_read(directory.file, out, sizeof(bfs512_DIRECTORY_ENTRY)); | |
| } | |
| //Scan a directory looking for a specific name. If found, return 1. 'out' will contain the entry. | |
| // If not found, return 0. 'out' will contain the last entry or garbage. | |
| function bfs512_scan_directory(file_system:bfs512_SYSTEM_HEADER, drive, sector, for, out:bfs512_DIRECTORY_ENTRY) | |
| { | |
| local _file:bfs512_OPEN_DIRECTORY[sizeof(bfs512_OPEN_DIRECTORY)]; | |
| local err = bfs512_open_directory(file_system, drive, sector, _file); | |
| if (err != BFS512_ERR_NONE) return err; | |
| local entry:bfs512_DIRECTORY_ENTRY[sizeof(bfs512_DIRECTORY_ENTRY)]; | |
| while (true) | |
| { | |
| err = bfs512_read_directory_entry(_file, entry); | |
| if (err != BFS512_ERR_NONE) return 0; | |
| if (bfs512_compare_filenames(entry.name, for) == 1) | |
| return 1; | |
| } | |
| } | |
| //Add a new entry to a directory file. | |
| function bfs512_append_to_directory(file_system:bfs512_SYSTEM_HEADER, drive, sector, what:bfs512_DIRECTORY_ENTRY) | |
| { | |
| local _file:bfs512_FILE[sizeof(bfs512_FILE)]; | |
| bfs512_open_read_write(_file, file_system, drive, sector); | |
| //Increment child_count | |
| local child_count = (_file.buffer):bfs512_DIRECTORY_HEADER.child_count; | |
| (_file.buffer):bfs512_DIRECTORY_HEADER.child_count += 1; | |
| //Seek to end of directory data. This will flush the first sector if the directory is larger than one sector. | |
| bfs512_seek(_file, (sizeof(bfs512_DIRECTORY_HEADER)) + (sizeof(bfs512_DIRECTORY_ENTRY) * child_count)); | |
| //Write the new entry. | |
| bfs512_write(_file, what, sizeof(bfs512_DIRECTORY_ENTRY)); | |
| bfs512_flush(_file); | |
| } | |
| //Remove an entry from a directory file. If the entry specified is >= child_count, this will explode. | |
| // This takes an entry index. To get it, scanning won't do. Use read_directory_entry and count until | |
| // you find the entry you want to remove. | |
| function bfs512_remove_from_directory(file_system:bfs512_SYSTEM_HEADER, drive, sector, entry_index) | |
| { | |
| local _file:bfs512_FILE[sizeof(bfs512_FILE)]; | |
| local temp_entry:bfs512_DIRECTORY_ENTRY[sizeof(bfs512_DIRECTORY_ENTRY)]; | |
| bfs512_open_read_write(_file, file_system, drive, sector); | |
| //Decrement child count. | |
| local child_count = (_file.buffer):bfs512_DIRECTORY_HEADER.child_count; | |
| (_file.buffer):bfs512_DIRECTORY_HEADER.child_count -= 1; | |
| //Find and read the last directory entry. | |
| bfs512_seek(_file, sizeof(bfs512_DIRECTORY_HEADER) + (sizeof(bfs512_DIRECTORY_ENTRY) * (child_count - 1))); | |
| bfs512_read(_file, temp_entry, sizeof(bfs512_DIRECTORY_ENTRY)); | |
| //If the file is only one sector long, seeking didn't flush it. Make sure it gets flushed. | |
| if (child_count > (((M35FD_SECTOR_SIZE - sizeof(bfs512_DIRECTORY_HEADER)) / sizeof(bfs512_DIRECTORY_ENTRY)))) | |
| bfs512_flush(_file); | |
| //Return to begining of file. | |
| bfs512_open_write(_file, file_system, drive, sector); | |
| //Write the last entry over the entry to be removed. | |
| bfs512_seek(_file, sizeof(bfs512_DIRECTORY_HEADER) + (sizeof(bfs512_DIRECTORY_ENTRY) * entry_index)); | |
| bfs512_write(_file, temp_entry, sizeof(bfs512_DIRECTORY_ENTRY)); | |
| bfs512_flush(_file); //Wrote to end of file. It -must- be flushed. | |
| //If removing the last entry shrunk the directory enough to discard a sector; discard it. | |
| local original_size = (sizeof(bfs512_DIRECTORY_HEADER) + (sizeof(bfs512_DIRECTORY_ENTRY) * child_count)) | |
| / M35FD_SECTOR_SIZE; | |
| local new_size = (sizeof(bfs512_DIRECTORY_HEADER) + (sizeof(bfs512_DIRECTORY_ENTRY) * (child_count - 1))) | |
| / M35FD_SECTOR_SIZE; | |
| if (new_size < original_size) | |
| { | |
| //Find the end of the file. | |
| local previous_sector = sector; | |
| local current_sector = sector; | |
| while (current_sector != 0xFFFF) | |
| { | |
| //If current_sector is linked to 0xFFFF, it is the last sector. Link the previous sector to 0xFFFF. | |
| local next_sector = bfs512_next_sector(file_system, current_sector); | |
| if (next_sector == 0xFFFF) | |
| bfs512_link_sectors(file_system, previous_sector, 0xFFFF); | |
| previous_sector = current_sector; | |
| current_sector = next_sector; | |
| } | |
| } | |
| } | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment