diff --git a/depends/quazip/JlCompress.cpp b/depends/quazip/JlCompress.cpp
index 69832140..19bf6246 100644
--- a/depends/quazip/JlCompress.cpp
+++ b/depends/quazip/JlCompress.cpp
@@ -1,7 +1,7 @@
 #include "JlCompress.h"
 #include <QDebug>
 
-static bool copyData(QIODevice &inFile, QIODevice &outFile)
+bool JlCompress::copyData(QIODevice &inFile, QIODevice &outFile)
 {
     while (!inFile.atEnd()) {
         char buf[4096];
diff --git a/depends/quazip/JlCompress.h b/depends/quazip/JlCompress.h
index 29d6191f..9679de7c 100644
--- a/depends/quazip/JlCompress.h
+++ b/depends/quazip/JlCompress.h
@@ -51,6 +51,8 @@ private:
     static bool removeFile(QStringList listFile);
 
 public:
+    /// copy data from inFile to outFile
+    static bool copyData(QIODevice &inFile, QIODevice &outFile);
     /// Compress a single file.
     /**
       \param fileCompressed The name of the archive.
diff --git a/depends/util/include/pathutils.h b/depends/util/include/pathutils.h
index 40bb9e74..cea3a39a 100644
--- a/depends/util/include/pathutils.h
+++ b/depends/util/include/pathutils.h
@@ -29,7 +29,17 @@ LIBUTIL_EXPORT QString RemoveInvalidFilenameChars(QString string, QChar replaceW
 
 LIBUTIL_EXPORT QString DirNameFromString(QString string, QString inDir = ".");
 
-LIBUTIL_EXPORT bool ensurePathExists(QString filenamepath);
+/**
+ * Creates all the folders in a path for the specified path
+ * last segment of the path is treated as a file name and is ignored!
+ */
+LIBUTIL_EXPORT bool ensureFilePathExists(QString filenamepath);
+
+/**
+ * Creates all the folders in a path for the specified path
+ * last segment of the path is treated as a folder name and is created!
+ */
+LIBUTIL_EXPORT bool ensureFolderPathExists(QString filenamepath);
 
 LIBUTIL_EXPORT bool copyPath(QString src, QString dst);
 
diff --git a/depends/util/src/pathutils.cpp b/depends/util/src/pathutils.cpp
index 5bafdf0f..0836567d 100644
--- a/depends/util/src/pathutils.cpp
+++ b/depends/util/src/pathutils.cpp
@@ -19,6 +19,7 @@
 #include <QDir>
 #include <QDesktopServices>
 #include <QUrl>
+#include <QDebug>
 
 QString PathCombine(QString path1, QString path2)
 {
@@ -68,24 +69,38 @@ QString DirNameFromString(QString string, QString inDir)
 	return dirName;
 }
 
-bool ensurePathExists(QString filenamepath)
+bool ensureFilePathExists(QString filenamepath)
 {
 	QFileInfo a ( filenamepath );
 	QDir dir;
-	return (dir.mkpath ( a.filePath() ));
+	QString ensuredPath = a.path();
+	bool success = dir.mkpath ( ensuredPath );
+	qDebug() << "ensureFilePathExists:" << success << ensuredPath << filenamepath;
+	return success;
 }
 
+bool ensureFolderPathExists(QString foldernamepath)
+{
+	QFileInfo a ( foldernamepath );
+	QDir dir;
+	QString ensuredPath = a.filePath();
+	bool success = dir.mkpath ( ensuredPath );
+	qDebug() << "ensureFolderPathExists:" << success << ensuredPath << foldernamepath;
+	return success;
+}
+
+
 bool copyPath(QString src, QString dst)
 {
 	QDir dir(src);
 	if (!dir.exists())
 		return false;
-	if(!ensurePathExists(dst))
+	if(!ensureFolderPathExists(dst))
 		return false;
 
 	foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
 	{
-		QString inner_src = src+ QDir::separator() + d;
+		QString inner_src = src + QDir::separator() + d;
 		QString inner_dst = dst + QDir::separator() + d;
 		copyPath(inner_src, inner_dst);
 	}
diff --git a/gui/LegacyModEditDialog.cpp b/gui/LegacyModEditDialog.cpp
index 51b21aa1..218e0979 100644
--- a/gui/LegacyModEditDialog.cpp
+++ b/gui/LegacyModEditDialog.cpp
@@ -28,9 +28,9 @@ LegacyModEditDialog::LegacyModEditDialog( LegacyInstance* inst, QWidget* parent
 	ui(new Ui::LegacyModEditDialog)
 {
 	ui->setupUi(this);
-	ensurePathExists(m_inst->coreModsDir());
-	ensurePathExists(m_inst->mlModsDir());
-	ensurePathExists(m_inst->jarModsDir());
+	ensureFolderPathExists(m_inst->coreModsDir());
+	ensureFolderPathExists(m_inst->mlModsDir());
+	ensureFolderPathExists(m_inst->jarModsDir());
 	
 	m_mods = m_inst->loaderModList();
 	m_coremods = m_inst->coreModList();
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp
index c2df34e1..bd2aad8a 100644
--- a/logic/BaseInstance.cpp
+++ b/logic/BaseInstance.cpp
@@ -42,6 +42,15 @@ BaseInstance::BaseInstance( BaseInstancePrivate* d_in,
 	settings().registerSetting(new Setting("notes", ""));
 	settings().registerSetting(new Setting("lastLaunchTime", 0));
 	
+	/*
+	 * custom base jar has no default. it is determined in code... see the accessor methods for it
+	 * 
+	 * for instances that DO NOT have the CustomBaseJar setting (legacy instances),
+	 * [.]minecraft/bin/mcbackup.jar is the default base jar
+	 */
+	settings().registerSetting(new Setting("UseCustomBaseJar", true));
+	settings().registerSetting(new Setting("CustomBaseJar", ""));
+	
 	// Java Settings
 	settings().registerSetting(new Setting("OverrideJava", false));
 	settings().registerSetting(new OverrideSetting("JavaPath", globalSettings->getSetting("JavaPath")));
@@ -121,6 +130,51 @@ SettingsObject &BaseInstance::settings() const
 	return *d->m_settings;
 }
 
+QString BaseInstance::baseJar() const
+{
+	I_D(BaseInstance);
+	bool customJar = d->m_settings->get("UseCustomBaseJar").toBool();
+	if(customJar)
+	{
+		return customBaseJar();
+	}
+	else
+		return defaultBaseJar();
+}
+
+QString BaseInstance::customBaseJar() const
+{
+	I_D(BaseInstance);
+	QString value = d->m_settings->get ( "CustomBaseJar" ).toString();
+	if(value.isNull() || value.isEmpty())
+	{
+		return defaultCustomBaseJar();
+	}
+	return value;
+}
+
+void BaseInstance::setCustomBaseJar ( QString val )
+{
+	I_D(BaseInstance);
+	if(val.isNull() || val.isEmpty() || val == defaultCustomBaseJar())
+		d->m_settings->reset ( "CustomBaseJar" );
+	else
+		d->m_settings->set ( "CustomBaseJar", val );
+}
+
+void BaseInstance::setShouldUseCustomBaseJar ( bool val )
+{
+	I_D(BaseInstance);
+	d->m_settings->set ( "UseCustomBaseJar", val );
+}
+
+bool BaseInstance::shouldUseCustomBaseJar() const
+{
+	I_D(BaseInstance);
+	return d->m_settings->get ( "UseCustomBaseJar" ).toBool();
+}
+
+
 qint64 BaseInstance::lastLaunch() const
 {
 	I_D(BaseInstance);
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index af721b04..48481e26 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -89,6 +89,25 @@ public:
 	 */
 	virtual bool shouldUpdate() const = 0;
 	virtual void setShouldUpdate(bool val) = 0;
+
+	/// Get the curent base jar of this instance. By default, it's the versions/$version/$version.jar
+	QString baseJar() const;
+
+	/// the default base jar of this instance
+	virtual QString defaultBaseJar() const = 0;
+	/// the default custom base jar of this instance
+	virtual QString defaultCustomBaseJar() const = 0;
+	
+	/*!
+	 * Whether or not custom base jar is used
+	 */
+	bool shouldUseCustomBaseJar() const;
+	void setShouldUseCustomBaseJar(bool val);
+	/*!
+	 * The value of the custom base jar
+	 */
+	QString customBaseJar() const;
+	void setCustomBaseJar(QString val);
 	
 	/**
 	 * Gets the time that the instance was last launched.
diff --git a/logic/IconListModel.cpp b/logic/IconListModel.cpp
index 2d2fb6cf..b531df43 100644
--- a/logic/IconListModel.cpp
+++ b/logic/IconListModel.cpp
@@ -39,8 +39,8 @@ IconList::IconList() : QAbstractListModel(), d(new Private())
 	}
 	
 	// FIXME: get from settings
-	ensurePathExists("icons/");
-	QDir user_icons("icons/");
+	ensureFolderPathExists("icons");
+	QDir user_icons("icons");
 	file_info_list = user_icons.entryInfoList(QDir::Files, QDir::Name);
 	for(auto file_info: file_info_list)
 	{
diff --git a/logic/InstanceFactory.cpp b/logic/InstanceFactory.cpp
index f3511157..f0630568 100644
--- a/logic/InstanceFactory.cpp
+++ b/logic/InstanceFactory.cpp
@@ -90,16 +90,19 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*&
 			m_settings->set("InstanceType", "Legacy");
 			inst = new LegacyInstance(instDir, m_settings, this);
 			inst->setIntendedVersionId(version->descriptor);
+			inst->setShouldUseCustomBaseJar(false);
 			break;
 		case MinecraftVersion::OneSix:
 			m_settings->set("InstanceType", "OneSix");
 			inst = new OneSixInstance(instDir, m_settings, this);
 			inst->setIntendedVersionId(version->descriptor);
+			inst->setShouldUseCustomBaseJar(false);
 			break;
 		case MinecraftVersion::Nostalgia:
 			m_settings->set("InstanceType", "Nostalgia");
 			inst = new NostalgiaInstance(instDir, m_settings, this);
 			inst->setIntendedVersionId(version->descriptor);
+			inst->setShouldUseCustomBaseJar(false);
 			break;
 		default:
 		{
diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp
index cf2c622c..9e191740 100644
--- a/logic/LegacyInstance.cpp
+++ b/logic/LegacyInstance.cpp
@@ -169,30 +169,25 @@ QString LegacyInstance::resourceDir() const
 	return PathCombine(minecraftRoot(), "resources");
 }
 
-QString LegacyInstance::mcJar() const
+QString LegacyInstance::runnableJar() const
 {
 	return PathCombine(binDir(), "minecraft.jar");
 }
 
-QString LegacyInstance::mcBackup() const
-{
-	return PathCombine(binDir(), "mcbackup.jar");
-}
-
 QString LegacyInstance::modListFile() const
 {
 	return PathCombine(instanceRoot(), "modlist");
 }
-
+/*
 bool LegacyInstance::shouldUpdateCurrentVersion() const
 {
-	QFileInfo jar(mcJar());
+	QFileInfo jar(runnableJar());
 	return jar.lastModified().toUTC().toMSecsSinceEpoch() != lastCurrentVersionUpdate();
 }
 
 void LegacyInstance::updateCurrentVersion(bool keepCurrent)
 {
-	QFileInfo jar(mcJar());
+	QFileInfo jar(runnableJar());
 	
 	if(!jar.exists())
 	{
@@ -221,6 +216,7 @@ void LegacyInstance::setLastCurrentVersionUpdate ( qint64 val )
 	I_D(LegacyInstance);
 	d->m_settings->set ( "lastVersionUpdate", val );
 }
+*/
 bool LegacyInstance::shouldRebuild() const
 {
 	I_D(LegacyInstance);
@@ -278,3 +274,14 @@ void LegacyInstance::setShouldUpdate ( bool val )
 {
 	settings().set ( "ShouldUpdate", val );
 }
+
+QString LegacyInstance::defaultBaseJar() const
+{
+	return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
+}
+
+QString LegacyInstance::defaultCustomBaseJar() const
+{
+	return PathCombine(binDir(), "mcbackup.jar");
+}
+
diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h
index 4c8d8f69..46c531d9 100644
--- a/logic/LegacyInstance.h
+++ b/logic/LegacyInstance.h
@@ -13,10 +13,7 @@ public:
 	explicit LegacyInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0);
 	
 	/// Path to the instance's minecraft.jar
-	QString mcJar() const;
-	
-	//! Path to the instance's mcbackup.jar
-	QString mcBackup() const;
+	QString runnableJar() const;
 	
 	//! Path to the instance's modlist file.
 	QString modListFile() const;
@@ -34,35 +31,6 @@ public:
 	QString coreModsDir() const;
 	QString resourceDir() const;
 	
-	/*!
-	 * \brief Checks whether or not the currentVersion of the instance needs to be updated. 
-	 *        If this returns true, updateCurrentVersion is called. In the 
-	 *        standard instance, this is determined by checking a timestamp 
-	 *        stored in the instance config file against the last modified time of Minecraft.jar.
-	 * \return True if updateCurrentVersion() should be called.
-	 */
-	bool shouldUpdateCurrentVersion() const;
-	
-	/*!
-	 * \brief Updates the current version. 
-	 *        This function should first set the current version timestamp 
-	 *        (setCurrentVersionTimestamp()) to the current time. Next, if 
-	 *        keepCurrent is false, this function should check what the 
-	 *        instance's current version is and call setCurrentVersion() to 
-	 *        update it. This function will automatically be called when the 
-	 *        instance is loaded if shouldUpdateCurrentVersion returns true.
-	 * \param keepCurrent If true, only the version timestamp will be updated.
-	 */
-	void updateCurrentVersion(bool keepCurrent = false); 
-	
-	/*!
-	 * Gets the last time that the current version was checked.
-	 * This is checked against the last modified time on the jar file to see if
-	 * the current version needs to be checked again.
-	 */
-	qint64 lastCurrentVersionUpdate() const;
-	void setLastCurrentVersionUpdate(qint64 val);
-	
 	/*!
 	 * Whether or not the instance's minecraft.jar needs to be rebuilt.
 	 * If this is true, when the instance launches, its jar mods will be 
@@ -90,6 +58,9 @@ public:
 	virtual void cleanupAfterRun();
 	virtual QDialog * createModEditDialog ( QWidget* parent );
 	
+	virtual QString defaultBaseJar() const;
+	virtual QString defaultCustomBaseJar() const;
+	
 protected slots:
 	virtual void jarModsChanged();
 };
\ No newline at end of file
diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp
index a748bad3..9644cb80 100644
--- a/logic/LegacyUpdate.cpp
+++ b/logic/LegacyUpdate.cpp
@@ -4,9 +4,11 @@
 #include "BaseInstance.h"
 #include "LegacyInstance.h"
 #include "net/NetWorker.h"
+#include "ModList.h"
 #include <pathutils.h>
 #include <quazip.h>
 #include <quazipfile.h>
+#include <JlCompress.h>
 
 
 LegacyUpdate::LegacyUpdate ( BaseInstance* inst, QObject* parent ) : BaseUpdate ( inst, parent ) {}
@@ -22,7 +24,7 @@ void LegacyUpdate::lwjglStart()
 
 	lwjglVersion =  inst->lwjglVersion();
 	lwjglTargetPath = PathCombine("lwjgl", lwjglVersion );
-	lwjglNativesPath = PathCombine( lwjglTargetPath, "natives/");
+	lwjglNativesPath = PathCombine( lwjglTargetPath, "natives");
 	
 	// if the 'done' file exists, we don't have to download this again
 	QFileInfo doneFile(PathCombine(lwjglTargetPath, "done"));
@@ -112,7 +114,7 @@ void LegacyUpdate::extractLwjgl()
 {
 	// make sure the directories are there
 
-	bool success = ensurePathExists(lwjglNativesPath);
+	bool success = ensureFolderPathExists(lwjglNativesPath);
 	
 	if(!success)
 	{
@@ -201,33 +203,14 @@ void LegacyUpdate::lwjglFailed()
 
 void LegacyUpdate::jarStart()
 {
-	setStatus("Checking ...");
 	LegacyInstance * inst = (LegacyInstance *) m_inst;
-	QString current_version_id = inst->currentVersionId();
-	QString intended_version_id = inst->intendedVersionId();
-	bool shouldUpdate = inst->shouldUpdate();
-	if(!shouldUpdate)
+	if(!inst->shouldUpdate() || inst->shouldUseCustomBaseJar())
 	{
-		emitSucceeded();
+		ModTheJar();
 		return;
 	}
 	
-	// nuke the backup file, we are replacing the base jar anyway
-	QFile mc_backup(inst->mcBackup());
-	if (mc_backup.exists())
-	{
-		mc_backup.remove();
-	}
-	
-	// Get a pointer to the version object that corresponds to the instance's version.
-	auto targetVersion = MinecraftVersionList::getMainList().findVersion(intended_version_id);
-	
-	if(!targetVersion)
-	{
-		emitFailed("Not a valid version:" + intended_version_id);
-		return;
-	}
-
+	setStatus("Checking for jar updates...");
 	// Make directories
 	QDir binDir(inst->binDir());
 	if (!binDir.exists() && !binDir.mkpath("."))
@@ -239,14 +222,11 @@ void LegacyUpdate::jarStart()
 	// Build a list of URLs that will need to be downloaded.
 	setStatus("Downloading new minecraft.jar");
 
-	// This will be either 'minecraft' or the version number, depending on where
-	// we're downloading from.
-	QString jarFilename = "minecraft";
-	QString download_path = PathCombine(inst->minecraftRoot(), "bin/minecraft.jar");
-
 	QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/");
-	urlstr += targetVersion->descriptor + "/" + targetVersion->descriptor + ".jar";
-	auto dljob = DownloadJob::create(QUrl(urlstr), download_path);
+	QString intended_version_id = inst->intendedVersionId();
+	urlstr += intended_version_id + "/" + intended_version_id + ".jar";
+	
+	auto dljob = DownloadJob::create(QUrl(urlstr), inst->defaultBaseJar());
 	
 	legacyDownloadJob.reset(new JobList());
 	legacyDownloadJob->add(dljob);
@@ -259,7 +239,7 @@ void LegacyUpdate::jarStart()
 void LegacyUpdate::jarFinished()
 {
 	// process the jar
-	emitSucceeded();
+	ModTheJar();
 }
 
 void LegacyUpdate::jarFailed()
@@ -268,74 +248,132 @@ void LegacyUpdate::jarFailed()
 	emitFailed("Failed to download the minecraft jar. Try again later.");
 }
 
+bool LegacyUpdate::MergeZipFiles( QuaZip* into, QFileInfo from, QSet< QString >& contained )
+{
+	setStatus("Installing mods - Adding " + from.fileName());
+	
+	QuaZip modZip(from.filePath());
+	modZip.open(QuaZip::mdUnzip);
+	
+	QuaZipFile fileInsideMod(&modZip);
+	QuaZipFile zipOutFile( into );
+	for(bool more=modZip.goToFirstFile(); more; more=modZip.goToNextFile())
+	{
+		QString filename = modZip.getCurrentFileName();
+		if(filename.contains("META-INF"))
+			continue;
+		if(contained.contains(filename))
+			continue;
+		contained.insert(filename);
+		qDebug() << "Adding file " << filename << " from " << from.fileName();
+		
+		if(!fileInsideMod.open(QIODevice::ReadOnly))
+		{
+			return false;
+		}
+		if(!zipOutFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileInsideMod.getActualFileName())))
+		{
+			fileInsideMod.close();
+			return false;
+		}
+		if(!JlCompress::copyData(fileInsideMod, zipOutFile))
+		{
+			zipOutFile.close();
+			fileInsideMod.close();
+			return false;
+		}
+		zipOutFile.close();
+		fileInsideMod.close();
+	}
+	return true;
+}
+
 void LegacyUpdate::ModTheJar()
 {
-	/*
 	LegacyInstance * inst = (LegacyInstance *) m_inst;
-	// Get the mod list
-	auto modList = inst->getJarModList();
 	
-	QFileInfo mcBin(inst->binDir());
-	QFileInfo mcJar(inst->mcJar());
-	QFileInfo mcBackup(inst->mcBackup());
-	
-	// Nothing to do if there are no jar mods to install, no backup and just the mc jar
-	if(mcJar.isFile() && !mcBackup.exists() && modList->empty())
+	if(!inst->shouldRebuild())
 	{
-		inst->setShouldRebuild(false);
 		emitSucceeded();
 		return;
 	}
 	
-	setStatus("Installing mods - backing up minecraft.jar...");
-	if (!mcBackup.exists() && !QFile::copy(mcJar.absoluteFilePath(), mcBackup.absoluteFilePath()) )
+	// Get the mod list
+	auto modList = inst->jarModList();
+	
+	QFileInfo runnableJar (inst->runnableJar());
+	QFileInfo baseJar (inst->baseJar());
+	bool base_is_custom = inst->shouldUseCustomBaseJar();
+	
+	// Nothing to do if there are no jar mods to install, no backup and just the mc jar
+	if(base_is_custom)
 	{
-		emitFailed("Failed to back up minecraft.jar");
+		// yes, this can happen if the instance only has the runnable jar and not the base jar
+		// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe
+		// because that's not something mmc4 guarantees
+		if(runnableJar.isFile() && !baseJar.exists() && modList->empty())
+		{
+			inst->setShouldRebuild(false);
+			emitSucceeded();
+			return;
+		}
+		
+		setStatus("Installing mods - backing up minecraft.jar...");
+		if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath()))
+		{
+			emitFailed("Failed to back up minecraft.jar");
+			return;
+		}
+	}
+	
+	if (!baseJar.exists())
+	{
+		emitFailed("The base jar " + baseJar.filePath() + " does not exist");
 		return;
 	}
 	
-	if (mcJar.isFile() && !QFile::remove(mcJar.absoluteFilePath()))
+	if (runnableJar.exists() && !QFile::remove(runnableJar.filePath()))
 	{
 		emitFailed("Failed to delete old minecraft.jar");
 		return;
 	}
 	
+	//TaskStep(); // STEP 1
 	setStatus("Installing mods - Opening minecraft.jar");
 
-	wxFFileOutputStream jarStream(mcJar.absoluteFilePath());
-	wxZipOutputStream zipOut(jarStream);
-
+	QuaZip zipOut(runnableJar.filePath());
+	if(!zipOut.open(QuaZip::mdCreate))
+	{
+		QFile::remove(runnableJar.filePath());
+		emitFailed("Failed to open the minecraft.jar for modding");
+		return;
+	}
 	// Files already added to the jar.
 	// These files will be skipped.
 	QSet<QString> addedFiles;
 
 	// Modify the jar
 	setStatus("Installing mods - Adding mod files...");
-	for (ModList::const_reverse_iterator iter = modList->rbegin(); iter != modList->rend(); iter++)
+	for (int i = modList->size() - 1; i >= 0; i--)
 	{
-		wxFileName modFileName = iter->GetFileName();
-		setStatus("Installing mods - Adding " + modFileName.GetFullName());
-		if (iter->GetModType() == Mod::ModType::MOD_ZIPFILE)
+		auto &mod = modList->operator[](i);
+		if (mod.type() == Mod::MOD_ZIPFILE)
 		{
-			wxFFileInputStream modStream(modFileName.GetFullPath());
-			wxZipInputStream zipStream(modStream);
-			std::unique_ptr<wxZipEntry> entry;
-			while (entry.reset(zipStream.GetNextEntry()), entry.get() != NULL)
+			if(!MergeZipFiles(&zipOut, mod.filename(), addedFiles))
 			{
-				if (entry->IsDir())
-					continue;
-
-				wxString name = entry->GetName();
-				if (addedFiles.count(name) == 0)
-				{
-					if (!zipOut.CopyEntry(entry.release(), zipStream))
-						break;
-					addedFiles.insert(name);
-				}
+				zipOut.close();
+				QFile::remove(runnableJar.filePath());
+				emitFailed("Failed to add " + mod.filename().fileName() + " to the jar.");
+				return;
 			}
 		}
-		else
+		else if (mod.type() == Mod::MOD_SINGLEFILE)
 		{
+			zipOut.close();
+			QFile::remove(runnableJar.filePath());
+			emitFailed("Loose files are NOT supported as jar mods.");
+			return;
+			/*
 			wxFileName destFileName = modFileName;
 			destFileName.MakeRelativeTo(m_inst->GetInstModsDir().GetFullPath());
 			wxString destFile = destFileName.GetFullPath();
@@ -348,34 +386,35 @@ void LegacyUpdate::ModTheJar()
 
 				addedFiles.insert(destFile);
 			}
+			*/
 		}
-	}
-
-	{
-		wxFFileInputStream inStream(mcBackup.GetFullPath());
-		wxZipInputStream zipIn(inStream);
-
-		std::auto_ptr<wxZipEntry> entry;
-		while (entry.reset(zipIn.GetNextEntry()), entry.get() != NULL)
+		else if (mod.type() == Mod::MOD_FOLDER)
 		{
-			wxString name = entry->GetName();
-
-			if (!name.Matches("META-INF*") &&
-				addedFiles.count(name) == 0)
-			{
-				if (!zipOut.CopyEntry(entry.release(), zipIn))
-					break;
-				addedFiles.insert(name);
-			}
+			zipOut.close();
+			QFile::remove(runnableJar.filePath());
+			emitFailed("Folders are NOT supported as jar mods.");
+			return;
 		}
 	}
 	
+	if(!MergeZipFiles(&zipOut, baseJar, addedFiles))
+	{
+		zipOut.close();
+		QFile::remove(runnableJar.filePath());
+		emitFailed("Failed to insert minecraft.jar contents.");
+		return;
+	}
+	
 	// Recompress the jar
-	TaskStep(); // STEP 3
-	SetStatus(_("Installing mods - Recompressing jar..."));
-
-	inst->SetNeedsRebuild(false);
-	inst->UpdateVersion(true);
-	return (ExitCode)1;
-	*/
+	zipOut.close();
+    if(zipOut.getZipError()!=0)
+	{
+		QFile::remove(runnableJar.filePath());
+		emitFailed("Failed to finalize minecraft.jar!");
+		return;
+    }
+	inst->setShouldRebuild(false);
+	//inst->UpdateVersion(true);
+	emitSucceeded();
+	return;
 }
\ No newline at end of file
diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h
index 342d1eab..a68d67bb 100644
--- a/logic/LegacyUpdate.h
+++ b/logic/LegacyUpdate.h
@@ -25,6 +25,8 @@
 
 class MinecraftVersion;
 class BaseInstance;
+class QuaZip;
+class Mod;
 
 class LegacyUpdate : public BaseUpdate
 {
@@ -46,6 +48,8 @@ private slots:
 	
 	void ModTheJar();
 private:
+	bool MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString>& contained);
+private:
 	
 	QSharedPointer<QNetworkReply> m_reply;
 	
@@ -59,9 +63,6 @@ private:
 private:
 	JobListPtr legacyDownloadJob;
 	JobListQueue download_queue;
-	
-	// target version, determined during this task
-	QSharedPointer<MinecraftVersion> targetVersion;
 };
 
 
diff --git a/logic/ModList.h b/logic/ModList.h
index 3cba69f5..61f3d596 100644
--- a/logic/ModList.h
+++ b/logic/ModList.h
@@ -37,6 +37,7 @@ public:
 	virtual int columnCount ( const QModelIndex& parent ) const;
 	
 	size_t size() const { return mods.size(); };
+	bool empty() const { return size() == 0; }
 	Mod& operator[](size_t index) { return mods[index]; };
 	
 	/// Reloads the mod list and returns true if the list changed.
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index b216c930..2eca7cd7 100644
--- a/logic/OneSixInstance.cpp
+++ b/logic/OneSixInstance.cpp
@@ -92,7 +92,7 @@ MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString sessi
 		return nullptr;
 	auto libs_to_extract = version->getActiveNativeLibs();
 	QString natives_dir_raw = PathCombine(instanceRoot(), "natives/");
-	bool success = ensurePathExists(natives_dir_raw);
+	bool success = ensureFolderPathExists(natives_dir_raw);
 	if(!success)
 	{
 		// FIXME: handle errors
@@ -216,3 +216,13 @@ QSharedPointer< FullVersion > OneSixInstance::getFullVersion()
 	I_D(OneSixInstance);
 	return d->version;
 }
+
+QString OneSixInstance::defaultBaseJar() const
+{
+	return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
+}
+
+QString OneSixInstance::defaultCustomBaseJar() const
+{
+	return PathCombine(instanceRoot(), "custom.jar");
+}
diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h
index 18f03a92..654b91dc 100644
--- a/logic/OneSixInstance.h
+++ b/logic/OneSixInstance.h
@@ -29,6 +29,9 @@ public:
 	bool reloadFullVersion();
 	/// get the current full version info
 	QSharedPointer<FullVersion> getFullVersion();
+	
+	virtual QString defaultBaseJar() const;
+	virtual QString defaultCustomBaseJar() const;
 private:
 	QStringList processMinecraftArgs( QString user, QString session );
 };
\ No newline at end of file
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index 2bb2f496..09d3cb14 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -91,7 +91,7 @@ void OneSixUpdate::versionFileFinished()
 	// save the version file in $instanceId/version.json
 	{
 		QString version1 =  PathCombine(inst_dir, "/version.json");
-		ensurePathExists(version1);
+		ensureFilePathExists(version1);
 		// FIXME: detect errors here, download to a temp file, swap
 		QFile  vfile1 (version1);
 		vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly );
diff --git a/logic/net/DownloadJob.cpp b/logic/net/DownloadJob.cpp
index ef842dfd..6d87a132 100644
--- a/logic/net/DownloadJob.cpp
+++ b/logic/net/DownloadJob.cpp
@@ -48,7 +48,7 @@ void DownloadJob::start()
 				m_expected_md5 = hash;
 			}
 		}
-		if(!ensurePathExists(filename))
+		if(!ensureFilePathExists(filename))
 		{
 			emit fail();
 			return;