Example #1
0
void apf_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "std";
		UINT32 size = core_fsize(m_file);
		int type = APF_STD;

		// attempt to identify Space Destroyer, which needs 1K of additional RAM
		if (size == 0x1800)
			type = APF_SPACEDST;
		if (size > 0x2000)
			type = APF_BASIC;

		slot_string = apf_get_slot(type);

		//printf("type: %s\n", slot_string);
		clear();

		result.cpy(slot_string);
		return;
	}

	software_get_default_slot(result, "std");
}
Example #2
0
bool path_iterator::next(astring &buffer, const char *name)
{
    // if none left, return FALSE to indicate we are done
    if (m_index != 0 && *m_current == 0)
        return false;

    // copy up to the next semicolon
    const char *semi = strchr(m_current, ';');
    if (semi == NULL)
        semi = m_current + strlen(m_current);
    buffer.cpy(m_current, semi - m_current);
    m_current = (*semi == 0) ? semi : semi + 1;

    // append the name if we have one
    if (name != NULL)
    {
        // compute the full pathname
        if (buffer.len() > 0)
            buffer.cat(PATH_SEPARATOR);
        buffer.cat(name);
    }

    // bump the index and return TRUE
    m_index++;
    return true;
}
Example #3
0
void xegs_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "xegs";
		dynamic_buffer head(0x10);
		UINT32 len = core_fsize(m_file);
		int type = A800_8K;
		
		// check whether there is an header, to identify the cart type
		if ((len % 0x1000) == 0x10)
		{
			core_fread(m_file, head, 0x10);		
			type = identify_cart_type(head);
		}
		if (type != A800_XEGS)
		{
			osd_printf_info("This game is not designed for XEGS. ");
			if (type >= A5200_4K)
				osd_printf_info("You might want to run it in A5200.\n");
			else
				osd_printf_info("You might want to run it in A800 or A800XL.\n");
		}
		
		slot_string = a800_get_slot(type);
		
		clear();
		
		result.cpy(slot_string);
	}
	else
		software_get_default_slot(result, "xegs");
}
Example #4
0
void a800_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "a800_8k";
		dynamic_buffer head(0x10);
		UINT32 len = core_fsize(m_file);
		int type = A800_8K;

		// check whether there is an header, to identify the cart type
		if ((len % 0x1000) == 0x10)
		{
			core_fread(m_file, head, 0x10);		
			type = identify_cart_type(head);
		}
		else	// otherwise try to guess based on size
		{
			if (len == 0x4000)
				type = A800_16K;
			if (len == 0x2000)
				type = A800_8K;
		}

		if (type >= A5200_4K)
			osd_printf_info("This game is not designed for A800. You might want to run it in A5200.\n");

		slot_string = a800_get_slot(type);
		
		clear();
		
		result.cpy(slot_string);
	}
	else
		software_get_default_slot(result, "a800_8k");
}
Example #5
0
void device_image_interface::software_get_default_slot(astring &result, const char *default_card_slot)
{
	const char *path = device().mconfig().options().value(instance_name());
	result.reset();
	if (strlen(path) > 0)
	{
		result.cpy(default_card_slot);
		software_part *swpart = find_software_item(path, true);
		if (swpart != NULL)
		{
			const char *slot = swpart->feature("slot");
			if (slot != NULL)
				result.cpy(slot);
		}
	}
}
Example #6
0
void sega8_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "rom";
		UINT32 len = core_fsize(m_file), offset = 0;
		dynamic_buffer rom(len);
		int type;

		core_fread(m_file, rom, len);

		if ((len % 0x4000) == 512)
			offset = 512;

		type = get_cart_type(rom + offset, len - offset);
		slot_string = sega8_get_slot(type);

		//printf("type: %s\n", slot_string);
		clear();

		result.cpy(slot_string);
		return;
	}

	software_get_default_slot(result, "rom");
}
Example #7
0
void a5200_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "a5200";
		dynamic_buffer head(0x10);
		UINT32 len = core_fsize(m_file);
		int type = A5200_8K;
		
		// check whether there is an header, to identify the cart type
		if ((len % 0x1000) == 0x10)
		{
			core_fread(m_file, head, 0x10);		
			type = identify_cart_type(head);

			astring info;
			if (hashfile_extrainfo(*this, info) && info == "A13MIRRORING")
				type = A5200_16K_2CHIPS;
		}
		if (type < A5200_4K)
			osd_printf_info("This game is not designed for A5200. You might want to run it in A800 or A800XL.\n");
		
		slot_string = a800_get_slot(type);
		
		clear();
		
		result.cpy(slot_string);
	}
	else
		software_get_default_slot(result, "a5200");
}
Example #8
0
chd_error chd_file::read_metadata(chd_metadata_tag searchtag, UINT32 searchindex, astring &output)
{
	// wrap this for clean reporting
	try
	{
		// if we didn't find it, just return
		metadata_entry metaentry;
		if (!metadata_find(searchtag, searchindex, metaentry))
			throw CHDERR_METADATA_NOT_FOUND;

		// read the metadata
		// TODO: how to properly allocate a dynamic char buffer?
		char* metabuf = new char[metaentry.length+1];
		memset(metabuf, 0x00, metaentry.length+1);
		file_read(metaentry.offset + METADATA_HEADER_SIZE, metabuf, metaentry.length);
		output.cpy(metabuf);
		delete[] metabuf;
		return CHDERR_NONE;
	}

	// just return errors
	catch (chd_error &err)
	{
		return err;
	}
}
Example #9
0
void device_image_interface::software_name_split(const char *swlist_swname, astring &swlist_name, astring &swname, astring &swpart)
{
	// reset all output parameters
	swlist_name.reset();
	swname.reset();
	swpart.reset();

	// if no colon, this is the swname by itself
	const char *split1 = strchr(swlist_swname, ':');
	if (split1 == NULL)
	{
		swname.cpy(swlist_swname);
		return;
	}

	// if one colon, it is the swname and swpart alone
	const char *split2 = strchr(split1 + 1, ':');
	if (split2 == NULL)
	{
		swname.cpy(swlist_swname, split1 - swlist_swname);
		swpart.cpy(split1 + 1);
		return;
	}

	// if two colons present, split into 3 parts
	swlist_name.cpy(swlist_swname, split1 - swlist_swname);
	swname.cpy(split1 + 1, split2 - (split1 + 1));
	swpart.cpy(split2 + 1);
}
Example #10
0
static bool find_include_file(astring &srcincpath, int srcrootlen, const astring &srcfile, const astring &filename)
{
	// iterate over include paths and find the file
	for (include_path *curpath = incpaths; curpath != NULL; curpath = curpath->next)
	{
		// a '.' include path is specially treated
		if (curpath->path == ".")
			srcincpath.cpysubstr(srcfile, 0, srcfile.rchr(0, PATH_SEPARATOR[0]));
		else
			srcincpath.cpy(curpath->path);

		// append the filename piecemeal to account for directories
		int lastsepindex = 0;
		int sepindex;
		while ((sepindex = filename.chr(lastsepindex, '/')) != -1)
		{
			astring pathpart(filename, lastsepindex, sepindex - lastsepindex);

			// handle .. by removing a chunk from the incpath
			if (pathpart == "..")
			{
				int sepindex_part = srcincpath.rchr(0, PATH_SEPARATOR[0]);
				if (sepindex_part != -1)
					srcincpath.substr(0, sepindex_part);
			}

			// otherwise, append a path separator and the pathpart
			else
				srcincpath.cat(PATH_SEPARATOR).cat(pathpart);

			// advance past the previous index
			lastsepindex = sepindex + 1;
		}

		// now append the filename
		srcincpath.cat(PATH_SEPARATOR).catsubstr(filename, lastsepindex, -1);

		// see if we can open it
		core_file *testfile;
		if (core_fopen(srcincpath, OPEN_FLAG_READ, &testfile) == FILERR_NONE)
		{
			// close the file
			core_fclose(testfile);
			return true;
		}
	}
	return false;
}
Example #11
0
void cbm_crt_get_card(astring &result, core_file *file)
{
	// read the header
	cbm_crt_header header;
	core_fread(file, &header, CRT_HEADER_LENGTH);

	if (memcmp(header.signature, CRT_SIGNATURE, 16) == 0)
	{
		UINT16 hardware = pick_integer_be(header.hardware, 0, 2);

		result.cpy(CRT_C64_SLOT_NAMES[hardware]);
		return;
	}

	result.reset();
}
Example #12
0
chd_file *ldplayer_state::get_disc()
{
	// open a path to the ROMs and find the first CHD file
	file_enumerator path(machine().options().media_path());

	// iterate while we get new objects
	const osd_directory_entry *dir;
	emu_file *image_file = NULL;
	chd_file *image_chd = NULL;
	while ((dir = path.next()) != NULL)
	{
		int length = strlen(dir->name);

		// look for files ending in .chd
		if (length > 4 &&
			dir->name[length - 4] == '.' &&
			tolower(dir->name[length - 3]) == 'c' &&
			tolower(dir->name[length - 2]) == 'h' &&
			tolower(dir->name[length - 1]) == 'd')
		{
			// open the file itself via our search path
			image_file = auto_alloc(machine(), emu_file(machine().options().media_path(), OPEN_FLAG_READ));
			file_error filerr = image_file->open(dir->name);
			if (filerr == FILERR_NONE)
			{
				// try to open the CHD
				chd_error chderr = chd_open_file(*image_file, CHD_OPEN_READ, NULL, &image_chd);
				if (chderr == CHDERR_NONE)
				{
					set_disk_handle(machine(), "laserdisc", *image_file, *image_chd);
					m_filename.cpy(dir->name);
					break;
				}
			}

			// close the file on failure
			auto_free(machine(), image_file);
			image_file = NULL;
		}
	}

	// if we failed, pop a message and exit
	if (image_file == NULL)
		throw emu_fatalerror("No valid image file found!\n");

	return get_disk_handle(machine(), "laserdisc");
}
Example #13
0
File: fileio.c Project: bji/libmame
bool path_iterator::next(astring &buffer)
{
	// if none left, return FALSE to indicate we are done
	if (m_index != 0 && *m_current == 0)
		return false;

	// copy up to the next semicolon
	const char *semi = strchr(m_current, ';');
	if (semi == NULL)
		semi = m_current + strlen(m_current);
	buffer.cpy(m_current, semi - m_current);
	m_current = (*semi == 0) ? semi : semi + 1;

	// bump the index and return TRUE
	m_index++;
	return true;
}
Example #14
0
chd_file *ldplayer_state::get_disc()
{
	bool found = FALSE;
	// open a path to the ROMs and find the first CHD file
	file_enumerator path(machine().options().media_path());

	// iterate while we get new objects
	const osd_directory_entry *dir;
	while ((dir = path.next()) != NULL)
	{
		int length = strlen(dir->name);

		// look for files ending in .chd
		if (length > 4 &&
			dir->name[length - 4] == '.' &&
			tolower(dir->name[length - 3]) == 'c' &&
			tolower(dir->name[length - 2]) == 'h' &&
			tolower(dir->name[length - 1]) == 'd')
		{
			// open the file itself via our search path
			emu_file image_file(machine().options().media_path(), OPEN_FLAG_READ);
			file_error filerr = image_file.open(dir->name);
			if (filerr == FILERR_NONE)
			{
				astring fullpath(image_file.fullpath());
				image_file.close();

				// try to open the CHD

				if (set_disk_handle(machine(), "laserdisc", fullpath) == CHDERR_NONE)
				{
					m_filename.cpy(dir->name);
					found = TRUE;
					break;
				}
			}
		}
	}

	// if we failed, pop a message and exit
	if (found == FALSE)
		throw emu_fatalerror("No valid image file found!\n");

	return get_disk_handle(machine(), "laserdisc");
}
Example #15
0
void vcs_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "a26_4k";
		UINT32 len = core_fsize(m_file);
		dynamic_buffer rom(len);
		int type;
		
		core_fread(m_file, rom, len);
		
		type = identify_cart_type(rom, len);
		slot_string = vcs_get_slot(type);
		
		clear();
		
		result.cpy(slot_string);
	}
	else
		software_get_default_slot(result, "a26_4k");
}
Example #16
0
void cheat_entry::menu_text(astring &description, astring &state, UINT32 &flags)
{
	// description is standard
	description.cpy(m_description);
	state.reset();
	flags = 0;

	// some cheat entries are just text for display
	if (is_text_only())
	{
		if (description)
		{
			description.trimspace();
			if (!description)
				description.cpy(MENU_SEPARATOR_ITEM);
		}
		flags = MENU_FLAG_DISABLE;
	}

	// if we have no parameter and no run or off script, it's a oneshot cheat
	else if (is_oneshot())
		state.cpy("Set");

	// if we have no parameter, it's just on/off
	else if (is_onoff())
	{
		state.cpy((m_state == SCRIPT_STATE_RUN) ? "On" : "Off");
		flags = (m_state != 0) ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW;
	}

	// if we have a value parameter, compute it
	else if (m_parameter != NULL)
	{
		if (m_state == SCRIPT_STATE_OFF)
		{
			state.cpy(is_oneshot_parameter() ? "Set" : "Off");
			flags = MENU_FLAG_RIGHT_ARROW;
		}
		else
		{
			state.cpy(m_parameter->text());
			flags = MENU_FLAG_LEFT_ARROW;
			if (!m_parameter->is_maximum())
				flags |= MENU_FLAG_RIGHT_ARROW;
		}
	}
}
Example #17
0
chd_file *ldplayer_state::get_disc()
{
	// open a path to the ROMs and find the first CHD file
	file_enumerator path(machine().options().media_path());

	// iterate while we get new objects
	const osd_directory_entry *dir;
	while ((dir = path.next()) != NULL)
	{
		int length = strlen(dir->name);

		// look for files ending in .chd
		if (length > 4 &&
			dir->name[length - 4] == '.' &&
			tolower(dir->name[length - 3]) == 'c' &&
			tolower(dir->name[length - 2]) == 'h' &&
			tolower(dir->name[length - 1]) == 'd')
		{
			// open the file itself via our search path
			emu_file image_file(machine().options().media_path(), OPEN_FLAG_READ);
			file_error filerr = image_file.open(dir->name);
			if (filerr == FILERR_NONE)
			{
				astring fullpath(image_file->fullpath();
				image_file.close();

				// try to open the CHD

				if (set_disk_handle(machine(), "laserdisc", fullpath) == CHDERR_NONE)
				{
					m_filename.cpy(dir->name);
					break;
				}
			}

			// close the file on failure
			auto_free(machine(), image_file);
			image_file = NULL;
		}
Example #18
0
void channelf_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "chess";
		UINT32 len = core_fsize(m_file);
		int type;

		if (len == 0x40000)
			type = CF_MULTI;
		else
			type = CF_CHESS;    // is there any way to detect the other carts from fullpath?

		slot_string = chanf_get_slot(type);

		//printf("type: %s\n", slot_string);
		clear();

		result.cpy(slot_string);
		return;
	}
	software_get_default_slot(result, "chess");
}
Example #19
0
void gba_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "gba_rom";
		UINT32 len = core_fsize(m_file);
		dynamic_buffer rom(len);
		int type;

		core_fread(m_file, rom, len);

		type = get_cart_type(rom, len);
		slot_string = gba_get_slot(type);

		//printf("type: %s\n", slot_string);
		clear();

		result.cpy(slot_string);
		return;
	}

	software_get_default_slot(result, "gba_rom");
}
Example #20
0
void o2_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "o2_rom";
		UINT32 size = core_fsize(m_file);
		int type = O2_STD;

		if (size == 12288)
			type = O2_ROM12;
		if (size == 16384)
			type = O2_ROM16;
		
		slot_string = o2_get_slot(type);

		//printf("type: %s\n", slot_string);
		clear();

		result.cpy(slot_string);
		return;
	}

	software_get_default_slot(result, "o2_rom");
}
Example #21
0
void msx_slot_cartridge_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "nomapper";
		UINT32 length = core_fsize(m_file);
		dynamic_buffer rom(length);
		int type = NOMAPPER;

		// Check if there's some mapper related information in the hashfiles
		astring extrainfo;
		if (hashfile_extrainfo(*this, extrainfo))
		{
			int extrainfo_type = -1;
			if (1 == sscanf(extrainfo.cstr(), "%d", &extrainfo_type))
			{
				static const struct { int extrainfo; int mapper; } extrainfo_map[] = {
					//{ 0, NOMAPPER },
					{ 1, MSXDOS2 },
					{ 2, KONAMI_SCC },
					{ 3, KONAMI },
					{ 4, ASCII8 },
					{ 5, ASCII16 },
					{ 6, GAMEMASTER2 },
					{ 7, ASCII8_SRAM },
					{ 8, ASCII16_SRAM },
					{ 9, RTYPE },
					{ 10, MAJUTSUSHI },
					{ 11, FMPAC },
					{ 12, SUPERLODERUNNER },
					{ 13, SYNTHESIZER },
					{ 14, CROSSBLAIM },
					{ 15, DISK_ROM },
					{ 16, KOREAN_80IN1 },
					{ 17, KOREAN_126IN1 }
				};

				for (int i = 0; i < ARRAY_LENGTH(extrainfo_map); i++)
				{
					if (extrainfo_map[i].extrainfo == extrainfo_type)
					{
						type = extrainfo_map[i].mapper;
					}
				}
			}
		}

		if (type == NOMAPPER)
		{
			// Not identified through hashfile, try automatic detection
			type = get_cart_type(rom, length);
		}

		if (type > NOMAPPER)
		{
			slot_string = msx_cart_get_slot_option(type);
		}

		result.cpy(slot_string);
		return;
	}
	software_get_default_slot(result, "nomapper");
}
Example #22
0
file_error zippath_fopen(const char *filename, UINT32 openflags, core_file *&file, astring &revised_path)
{
	file_error filerr = FILERR_NOT_FOUND;
	zip_error ziperr;
	zip_file *zip = NULL;
	const zip_file_header *header;
	osd_dir_entry_type entry_type;
	char *alloc_fullpath = NULL;
	int len;

	/* first, set up the two types of paths */
	astring mainpath(filename);
	astring subpath;
	file = NULL;

	/* loop through */
	while((file == NULL) && (mainpath.len() > 0)
		&& ((openflags == OPEN_FLAG_READ) || (subpath.len() == 0)))
	{
		/* is the mainpath a ZIP path? */
		if (is_zip_file(mainpath))
		{
			/* this file might be a zip file - lets take a look */
			ziperr = zip_file_open(mainpath, &zip);
			if (ziperr == ZIPERR_NONE)
			{
				/* it is a zip file - error if we're not opening for reading */
				if (openflags != OPEN_FLAG_READ)
				{
					filerr = FILERR_ACCESS_DENIED;
					goto done;
				}

				if (subpath.len() > 0)
					header = zippath_find_sub_path(zip, subpath, &entry_type);
				else
					header = zip_file_first_file(zip);

				if (header == NULL)
				{
					filerr = FILERR_NOT_FOUND;
					goto done;
				}

				/* attempt to read the file */
				filerr = create_core_file_from_zip(zip, header, file);
				if (filerr != FILERR_NONE)
					goto done;

				/* update subpath, if appropriate */
				if (subpath.len() == 0)
					subpath.cpy(header->filename);

				/* we're done */
				goto done;
			}
		}
		else if (is_7z_file(mainpath))
		{
			filerr = FILERR_INVALID_DATA;
			goto done;
		}

		if (subpath.len() == 0)
			filerr = core_fopen(filename, openflags, &file);
		else
			filerr = FILERR_NOT_FOUND;

		/* if we errored, then go up a directory */
		if (filerr != FILERR_NONE)
		{
			/* go up a directory */
			astring temp;
			zippath_parent(temp, mainpath);

			/* append to the sub path */
			if (subpath.len() > 0)
			{
				astring temp2;
				temp2.cpysubstr(mainpath, temp.len()).cat(PATH_SEPARATOR).cat(subpath);
				subpath.cpy(temp2);
			}
			else
				subpath.cpysubstr(mainpath, temp.len());

			/* get the new main path, truncating path separators */
			len = temp.len();
			while (len > 0 && is_zip_file_separator(temp[len - 1]))
				len--;
			mainpath.cpysubstr(temp, 0, len);
		}
	}

done:
	/* store the revised path */
	revised_path.reset();
	if (filerr == FILERR_NONE)
	{
		/* cannonicalize mainpath */
		filerr = osd_get_full_path(&alloc_fullpath, mainpath);
		if (filerr == FILERR_NONE)
		{
			if (subpath.len() > 0)
				revised_path.cpy(alloc_fullpath).cat(PATH_SEPARATOR).cat(subpath);
			else
				revised_path.cpy(alloc_fullpath);
		}
	}

	if (zip != NULL)
		zip_file_close(zip);
	if (alloc_fullpath != NULL)
		osd_free(alloc_fullpath);
	return filerr;
}
Example #23
0
void a78_cart_slot_device::get_default_card_software(astring &result)
{
	if (open_image_file(mconfig().options()))
	{
		const char *slot_string = "a78_rom";
		dynamic_buffer head(128);
		int type = A78_TYPE0, mapper;

		// Load and check the header
		core_fread(m_file, head, 128);

		// let's try to auto-fix some common errors in the header
		mapper = validate_header((head[53] << 8) | head[54], FALSE);

		switch (mapper & 0x2e)
		{
			case 0x0000:
				type = BIT(mapper, 0) ? A78_TYPE1 : A78_TYPE0;
				break;
			case 0x0002:
				type = BIT(mapper, 0) ? A78_TYPE3 : A78_TYPE2;
				break;
			case 0x0006:
				type = A78_TYPE6;
				break;
			case 0x000a:
				type = A78_TYPEA;
				break;
			case 0x0022:
			case 0x0026:
				if (core_fsize(m_file) > 0x40000)
					type = A78_MEGACART;
				else
					type = A78_VERSABOARD;
				break;
		}

		// check if cart has a POKEY at $0450 (typically a VersaBoard variant)!
		if (mapper & 0x40)
		{
			if (type != A78_TYPE2)
			{
				type &= ~0x02;
				type += A78_POKEY0450;
			}
		}

		// check special bits, which override the previous
		if ((mapper & 0xff00) == 0x0100)
			type = A78_ACTIVISION;
		else if ((mapper & 0xff00) == 0x0200)
			type = A78_ABSOLUTE;

		logerror("Cart type: %x\n", type);
		slot_string = a78_get_slot(type);

		clear();

		result.cpy(slot_string);
	}
	else
		software_get_default_slot(result, "a78_rom");
}
Example #24
0
static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, astring &newpath)
{
	file_error err;
	osd_directory_entry *current_entry = NULL;
	osd_dir_entry_type current_entry_type;
	int went_up = FALSE;
	int i;

	newpath.reset();

	/* be conservative */
	entry_type = ENTTYPE_NONE;
	zipfile = NULL;

	astring apath(path);
	astring apath_trimmed;
	do
	{
		/* trim the path of trailing path separators */
		i = apath.len();
		while (i > 1 && is_path_separator(apath[i - 1]))
			i--;
		apath_trimmed.cpysubstr(apath, 0, i);

		/* stat the path */
		current_entry = osd_stat(apath_trimmed);

		/* did we find anything? */
		if (current_entry != NULL)
		{
			/* get the entry type and free the stat entry */
			current_entry_type = current_entry->type;
			osd_free(current_entry);
			current_entry = NULL;
		}
		else
		{
			/* if we have not found the file or directory, go up */
			current_entry_type = ENTTYPE_NONE;
			went_up = TRUE;
			astring parent;
			apath.cpy(zippath_parent(parent, apath));
		}
	}
	while (current_entry_type == ENTTYPE_NONE && !is_root(apath));

	/* if we did not find anything, then error out */
	if (current_entry_type == ENTTYPE_NONE)
	{
		err = FILERR_NOT_FOUND;
		goto done;
	}

	/* is this file a ZIP file? */
	if ((current_entry_type == ENTTYPE_FILE) && is_zip_file(apath_trimmed)
		&& (zip_file_open(apath_trimmed, &zipfile) == ZIPERR_NONE))
	{
		i = strlen(path + apath.len());
		while (i > 0 && is_zip_path_separator(path[apath.len() + i - 1]))
			i--;
		newpath.cpy(path + apath.len(), i);

		/* this was a true ZIP path - attempt to identify the type of path */
		zippath_find_sub_path(zipfile, newpath, &current_entry_type);
		if (current_entry_type == ENTTYPE_NONE)
		{
			err = FILERR_NOT_FOUND;
			goto done;
		}
	}
	else
	{
		/* this was a normal path */
		if (went_up)
		{
			err = FILERR_NOT_FOUND;
			goto done;
		}
		newpath.cpy(path);
	}

	/* success! */
	entry_type = current_entry_type;
	err = FILERR_NONE;

done:
	return err;
}