/* DOS/Win16 path and environment helpers used by CTL3D discovery. */ #include "tdkpin_multimedia.h" #include "tdkpin_strings.h" /* * 1008:2608 -- copy at most 79 ANSI bytes to a stack ASCIIZ buffer, translate * it in-place to OEM, then issue DOS AX=4300h. The helper's original register * interface preserves CX for the returned attributes; the typed bridge makes * carry and that CX value explicit. */ Win16DosFileAttributesResult borland_dos_get_file_attributes_ansi( Win16FarPtr name) { uint8_t oem_name[80]; uint16_t copied = 0; while (copied < 79) { uint8_t byte = win16_read_u8(win16_far_add_offset(name, copied)); if (byte == 0) { break; } oem_name[copied++] = byte; } oem_name[copied] = 0; Win16FarPtr local = win16_stack_pointer(oem_name); (void)AnsiToOem16(local, local); return win16_dos_get_file_attributes(local); } static uint16_t append_c_string( Win16FarPtr output, uint16_t cursor, uint16_t *remaining, Win16FarPtr source) { uint16_t source_index = 0; while (*remaining != 0) { uint8_t byte = win16_read_u8( win16_far_add_offset(source, source_index++)); if (byte == 0) { break; } win16_write_u8(win16_far_add_offset(output, cursor++), byte); (*remaining)--; } win16_write_u8(win16_far_add_offset(output, cursor), 0); return cursor; } /* * 1008:2643 -- search for file_name first as given, then under each semicolon- * separated directory. Result capacity is exactly 79 characters plus NUL. * DOS volume labels/directories (attribute bits 08/10) do not count as files. */ Win16FarPtr multimedia_search_file( Win16FarPtr search_path, Win16FarPtr file_name, Win16FarPtr result) { uint16_t search_index = 0; uint16_t remaining = 79; uint16_t cursor = append_c_string(result, 0, &remaining, file_name); for (;;) { Win16DosFileAttributesResult attributes = borland_dos_get_file_attributes_ansi(result); if (!attributes.carry && (attributes.attributes & 0x18u) == 0) { return result; } remaining = 79; cursor = 0; uint8_t character = win16_read_u8( win16_far_add_offset(search_path, search_index)); uint8_t last_copied = 0; if (character == 0) { win16_write_u8(result, 0); return result; } for (;;) { search_index++; if (character == ';') { break; } if (remaining != 0) { last_copied = character; win16_write_u8( win16_far_add_offset(result, cursor++), character); remaining--; } character = win16_read_u8( win16_far_add_offset(search_path, search_index)); if (character == 0) { break; } } if (remaining != 0 && last_copied != ':' && last_copied != '\\') { win16_write_u8(win16_far_add_offset(result, cursor++), '\\'); remaining--; } cursor = append_c_string( result, cursor, &remaining, file_name); } } /* * 1008:26b0 -- Borland-style path splitter. Optional outputs receive the * directory/drive prefix (max 67), basename (max 8), and extension (max 4). * Return bits are 8 wildcard, 4 prefix, 2 basename, and 1 extension. */ uint16_t multimedia_split_path( Win16FarPtr extension, Win16FarPtr file_name, Win16FarPtr directory, Win16FarPtr input) { Win16FarPtr base = borland_far_strrchr(input, '\\'); if (base == 0) { base = borland_far_strrchr(input, ':'); } if (base == 0) { base = input; } else { base = win16_far_add_offset(base, 1); } Win16FarPtr dot = borland_far_strchr(base, '.'); if (dot == 0) { dot = borland_far_strend(base); } uint16_t prefix_length = (uint16_t)( win16_far_offset(base) - win16_far_offset(input)); if (prefix_length > 0x43) { prefix_length = 0x43; } uint16_t name_length = (uint16_t)( win16_far_offset(dot) - win16_far_offset(base)); if (name_length > 8) { name_length = 8; } uint16_t flags = 0; if (borland_far_strchr(base, '?') != 0 || borland_far_strchr(base, '*') != 0) { flags |= 8; } if (prefix_length != 0) { flags |= 4; } if (name_length != 0) { flags |= 2; } if (win16_read_u8(dot) != 0) { flags |= 1; } if (directory != 0) { (void)borland_far_strncpy(directory, input, prefix_length); } if (file_name != 0) { (void)borland_far_strncpy(file_name, base, name_length); } if (extension != 0) { (void)borland_far_strncpy(extension, dot, 4); } return flags; } /* 1008:2819 -- case-insensitive NAME= lookup in the DOS environment block. */ Win16FarPtr multimedia_environment_value(Win16FarPtr name) { uint16_t name_length = borland_far_strlen(name); Win16FarPtr variable = GetDOSEnvironment16(); while (win16_read_u8(variable) != 0) { if (borland_far_strnicmp(name, variable, name_length) == 0 && win16_read_u8(win16_far_add_offset(variable, name_length)) == '=') { return win16_far_add_offset(variable, (uint16_t)(name_length + 1)); } variable = win16_far_add_offset( variable, (uint16_t)(borland_far_strlen(variable) + 1)); } return 0; }