Merge pull request #708 from AnBui2004/master

4.4.7
This commit is contained in:
An Bui 2026-07-27 18:14:06 +07:00 committed by GitHub
commit eda3e765db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
54 changed files with 779 additions and 291 deletions

View file

@ -33,10 +33,15 @@ QEMU 11.0.0 (for Vectras VM 4.0.8+):
- [See more at the Internet Archive](https://archive.org/details/qemu-11-0-0-for-vectras-vm-nbab)
QEMU 9.2.4 - 3dfx (only for Vectras VM 3.5.0):
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.0/base-nosve-vectras-vm-arm64-v8a.tar.gz)
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.0/base-vectras-vm-x86_64.tar.gz)
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-9.2.2-3dfx-july-2026-vectras-vm-arm64-v8a.tar.gz)
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-9.2.2-3dfx-july-2026-vectras-vm-x86_64.tar.gz)
- [See them at the Internet Archive](https://archive.org/details/qemu-9-2-4-3dfx-for-vectras-vm-nbab)
QEMU 9.2.2 - 3dfx (recommended and for Vectras VM 4.4.7+):
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.1/base-genegic-nosve-vectras-vm-arm64-v8a.tar.gz)
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.1/base-generic-vectras-vm-x86_64.tar.gz)
- [See them at the Internet Archive](https://archive.org/details/qemu-9-2-2-3dfx-for-vectras-vm-nbab)
QEMU 9.2.2 - 3dfx (recommended and for Vectras VM 4.1.1+):
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.1.1/base-may-2026-vectras-vm-arm64-v8a.tar.gz)
- [See them at the Internet Archive](https://archive.org/details/qemu-9-2-2-3dfx-for-vectras-vm-nbab)
@ -59,6 +64,14 @@ QEMU 8.2.0 - 3dfx (only for Vectras VM 2.9.5):
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.2.9/vectras-vm-x86_64.tar.gz)
- [See them at the Internet Archive](https://archive.org/details/vectras-vm-x86_64.tar_202603nbab)
QEMU 7.2.22 - 3dfx (for Vectras VM 4.4.7+):
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-arm64-v8a.tar.gz)
- [For Android ARM (32-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-july-2026-vectras-vm-armeabi-v7a.tar.gz)
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-x86_64.tar.gz)
- [For Android x86 (32-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-july-2026-vectras-vm-x86.tar.gz)
- [See more at the Internet Archive (64-bit)](https://archive.org/details/qemu-7-2-22-for-vectras-vm-nbab)
- [See more at the Internet Archive (32-bit)](https://archive.org/details/qemu-7-2-22-for-vectras-vm-nbab0)
QEMU 7.2.22 - 3dfx (for Vectras VM 4.2.2+):
- [For Android ARM (64-bit)](https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-june-2026-vectras-vm-arm64-v8a.tar.gz)
- [See more at the Internet Archive](https://archive.org/details/qemu-7-2-22-for-vectras-vm-nbab)

View file

@ -77,12 +77,12 @@ We publish a **new beta release after every commit** — so you can always test
[![Download Beta](https://img.shields.io/badge/Download-Beta-blue?style=for-the-badge&logo=github)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases)
### ⚙️ Bootstraps
QEMU 9.2.2 - 3dfx is here!
QEMU 7.2.22 - 3dfx is here!
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.1.1/base-may-2026-vectras-vm-arm64-v8a.tar.gz)
- [For Android ARM (32-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.4/base-vectras-vm-armeabi-v7a.tar.gz)
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.1/base-generic-vectras-vm-x86_64.tar.gz)
- [For Android x86 (32-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.4/base-vectras-vm-x86.tar.gz)
- [For Android ARM (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-arm64-v8a.tar.gz)
- [For Android ARM (32-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-july-2026-vectras-vm-armeabi-v7a.tar.gz)
- [For Android x86 (64-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-x86_64.tar.gz)
- [For Android x86 (32-bit)](https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-july-2026-vectras-vm-x86.tar.gz)
### 💽 3Dfx Wrappers
Play classic games with 3Dfx support on Windows 95, 98, ME, 2000, and XP! Turnip & Zink will help improve performance if your device has a supported Adreno GPU. Note: It may be unstable and have low performance.

View file

@ -13,8 +13,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 153
versionName "4.4.6"
versionCode 154
versionName "4.4.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

Binary file not shown.

Binary file not shown.

View file

@ -18,11 +18,11 @@ public class AppConfig {
// App Config
public static String vectrasVersion;
public static int vectrasVersionCode;
public static final int standardSetupVersion = 922202606;
public static final int standardSetupVersion = 922202607;
public static final int coreSetupVersion = 0;
public static String vectrasWebsite = "https://vectras.vercel.app/";
public static String vectrasWebsiteRaw = "https://raw.githubusercontent.com/AnBui2004/Vectras-VM-Emu-Android/refs/heads/master/web/";
public static String bootstrapfileslink = vectrasWebsiteRaw + "/data/setupfiles3.json";
public static String bootstrapfileslink = vectrasWebsiteRaw + "/data/setupfiles4.json";
public static String vectrasHelp = vectrasWebsite + "how.html";
public static String community = vectrasWebsite + "community.html";
public static String vectrasRaw = vectrasWebsiteRaw + "data/";

View file

@ -208,6 +208,8 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("wifi", current.wifi);
vmConfigMap.put("soundCard", current.soundCard);
vmConfigMap.put("bootFrom", current.bootFrom);
vmConfigMap.put("isShowBootMenu", current.isShowBootMenu);
vmConfigMap.put("isUseLocalTime", current.isUseLocalTime);

View file

@ -18,6 +18,7 @@ import androidx.core.app.NotificationCompat;
import com.vectras.vm.main.core.MainStartVM;
import com.vectras.vm.manager.VmServiceManager;
import com.vectras.vm.settings.SettingsData;
import com.vectras.vm.utils.ClipboardUltils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vterm.Terminal2;
@ -132,6 +133,8 @@ public class MainService extends Service {
MainStartVM.dismissDialog();
if (!VMManager.isExecutedCommandError(command, log, context)) {
if (!SettingsData.alwaysShowLog(context) && status == terminal2.SUCCESS) return;
String finalLog = log.contains(MainStartVM.TAG_FINISHED_WITHOUT_ERROR) ? log.substring(0, log.lastIndexOf(MainStartVM.TAG_FINISHED_WITHOUT_ERROR) - 1) : log;
DialogUtils.twoDialog(context, vmName, finalLog, context.getString(R.string.copy), context.getString(R.string.close), true, R.drawable.stack_24px, true,

View file

@ -66,7 +66,7 @@ public class StartVM {
if (
vmConfigs.nvirt &&
!MainSettingsManager.getArch(activity).equals(MainSettingsManager.PPC_ARCH) &&
MainSettingsManager.getArch(activity).equals(MainSettingsManager.ARM64_ARCH)
MainSettingsManager.getArch(activity).equals(MainSettingsManager.ARM64_ARCH)
) {
machineParams += ",virtualization=true";
}
@ -129,23 +129,43 @@ public class StartVM {
}
}
if (!memoryParams.isEmpty()) memoryParams += " ";
String networkParams = "";
String network = Objects.requireNonNull(VMCreatorSelector.getNetworkCard(activity, vmData.networkCard).get("value")).toString();
if (!network.isEmpty()) {
networkParams = " -device " + network + ",netdev=net0 -netdev user,id=net0";
String netDevId = "netdev" + System.currentTimeMillis();
networkParams = " -device " + network + ",netdev=" + netDevId + " -netdev user,id=" + netDevId;
}
String soundParams = "";
String sound = Objects.requireNonNull(VMCreatorSelector.getSoundCard(activity, vmData.soundCard).get("value")).toString();
if (!sound.isEmpty()) {
String audioDevId = "audiodev" + System.currentTimeMillis();
soundParams = " -device " +
sound +
(
sound.contains("intel-hda") ?
" -device hda-duplex" :
""
) +
",audiodev=" +
audioDevId +
" -audiodev wav,id=" +
audioDevId +
",out.frequency=48000,path=" +
VmFileManager.getAudioRaw(VectrasApp.getContext(), vmConfigs.vmID);
}
String bootFromParams = Objects.requireNonNull(VMCreatorSelector.getBootFrom(activity, vmData.bootFrom).get("value")).toString();
String showBootMenuParams = vmData.isShowBootMenu ? "menu=on" : "";
String bootParams = "";
if (!bootFromParams.isEmpty() || !showBootMenuParams.isEmpty()) {
bootParams = "-boot " + bootFromParams + (!bootFromParams.isEmpty() && !showBootMenuParams.isEmpty() ? "," : "") + showBootMenuParams + " ";
bootParams = " -boot " + bootFromParams + (!bootFromParams.isEmpty() && !showBootMenuParams.isEmpty() ? "," : "") + showBootMenuParams + " ";
}
extraParams = machineParams + cpuParams + memoryParams + bootParams + networkParams + " " + extraParams;
extraParams = machineParams + cpuParams + memoryParams + bootParams + networkParams + soundParams + " " + extraParams;
return env(activity, extraParams, vmData.itemPath, false);
}
@ -204,21 +224,10 @@ public class StartVM {
}
if (!vmConfigs.hd1.isEmpty()) {
if (ifType.isEmpty()) {
hdd0 = "-hdb";
hdd0 += " '" + vmConfigs.hd1 + "'";
} else {
hdd0 = "-drive";
hdd0 += " media=disk";
hdd0 += ",if=" + ifType;
hdd0 += ",file='" + vmConfigs.hd1 + "'";
hdd0 = "-drive";
hdd0 += " media=disk";
hdd0 += ",file='" + vmConfigs.hd1 + "'";
if ((MainSettingsManager.getArch(activity).equals("ARM64") && ifType.equals("ide")) || MainSettingsManager.getArch(activity).equals("PPC")) {
hdd0 = "-drive";
hdd0 += " media=disk";
hdd0 += ",file='" + vmConfigs.hd1 + "'";
}
}
params.add(hdd0);
}
@ -255,14 +264,9 @@ public class StartVM {
cdromParams += " -drive";
cdromParams += " if=none,id=cdromdrive1,format=raw,media=cdrom,file='" + vmConfigs.cdrom1 + "'";
} else {
if (vmConfigs.imgCdrom.isEmpty() && !extras.contains("-cdrom ")) {
cdromParams = "-cdrom";
cdromParams += " '" + vmConfigs.cdrom1 + "'";
} else {
cdromParams = "-drive";
cdromParams += " media=cdromdrive1";
cdromParams += ",file='" + vmConfigs.cdrom1 + "'";
}
cdromParams = "-drive";
cdromParams += " media=cdromdrive1";
cdromParams += ",file='" + vmConfigs.cdrom1 + "'";
}
params.add(cdromParams);
}
@ -270,44 +274,19 @@ public class StartVM {
File hdd1File = new File(filesDir + "/data/Vectras/hdd1.qcow2");
if (hdd1File.exists()) {
if (ifType.isEmpty()) {
hdd1 = "-hdb";
hdd1 += " '" + hdd1File.getPath() + "'";
} else {
hdd1 = "-drive";
hdd1 += " media=disk";
hdd1 += ",if=" + ifType;
hdd1 += ",file='" + hdd1File.getPath() + "'";
}
hdd1 = "-drive";
hdd1 += " media=disk";
hdd1 += ",file='" + hdd1File.getPath() + "'";
params.add(hdd1);
}
if (!vmConfigs.fda.isEmpty() && !MainSettingsManager.getArch(activity).equals("ARM64")) {
if (extras.contains("-fda ")) {
params.add("-drive if=floppy,file='" + vmConfigs.fda + "'");
} else {
params.add("-fda");
params.add("'" + vmConfigs.fda + "'");
}
params.add("-drive if=floppy,file='" + vmConfigs.fda + "'");
}
if (!vmConfigs.fdb.isEmpty() && !MainSettingsManager.getArch(activity).equals("ARM64")) {
if (vmConfigs.fda.isEmpty()) {
if (extras.contains("-fda ")) {
params.add("-drive if=floppy,file='" + vmConfigs.fdb + "'");
} else {
params.add("-fda");
params.add("'" + vmConfigs.fdb + "'");
}
} else {
if (extras.contains("-fdb ")) {
params.add("-drive if=floppy,file='" + vmConfigs.fdb + "'");
} else {
params.add("-fdb");
params.add("'" + vmConfigs.fdb + "'");
}
}
params.add("-drive if=floppy,file='" + vmConfigs.fdb + "'");
}
if (vmConfigs.sharedFolder) {
@ -317,90 +296,43 @@ public class StartVM {
params.add(driveParams);
}
// String boot = "-boot ";
// if (extras.contains(".iso ")) {
//
// boot += MainSettingsManager.getBoot(activity);
// } else {
// boot += "c";
// }
//String soundDevice = "-audiodev pa,id=pa -device AC97,audiodev=pa";
//params.add(soundDevice);
if (vmConfigs.isUseDefaultBios) {
extractFirmware(activity);
if (MainSettingsManager.getArch(activity).equals("PPC")) {
bios = "-L ";
bios += "pc-bios";
} else if (MainSettingsManager.getArch(activity).equals("ARM64")) {
if (!FileUtils.isFileExists(VmFileManager.getPath(vmConfigs.vmID, "QEMU_VARS.img")))
FileUtils.copyFile(AppConfig.basefiledir + "QEMU_VARS.img", VmFileManager.getPath(vmConfigs.vmID));
bios = "-drive ";
bios += "file=" + AppConfig.basefiledir + "QEMU_EFI.img,format=raw,readonly=on,if=pflash";
bios += " -drive ";
bios += "file=" + AppConfig.basefiledir + "QEMU_VARS.img,format=raw,if=pflash";
bios += "file=" + VmFileManager.getPath(vmConfigs.vmID, "QEMU_VARS.img") + ",format=raw,if=pflash";
} else if (vmConfigs.isUseUefi) {
String codeFile = "edk2-" + MainSettingsManager.getArch(activity).toLowerCase() + "-code.fd";
String varsFile = "edk2-" + MainSettingsManager.getArch(activity).toLowerCase() + "-vars.fd";
if (!FileUtils.isFileExists(VmFileManager.getPath(vmConfigs.vmID, varsFile)))
FileUtils.copyFile(AppConfig.basefiledir + varsFile, VmFileManager.getPath(vmConfigs.vmID));
bios = "-drive ";
bios += "file=" + AppConfig.basefiledir + "RELEASEX64_OVMF.fd,format=raw,readonly=on,if=pflash";
bios += "file=" + AppConfig.basefiledir + codeFile + ",format=raw,readonly=on,if=pflash";
bios += " -drive ";
bios += "file=" + AppConfig.basefiledir + "RELEASEX64_OVMF_VARS.fd,format=raw,if=pflash";
bios += "file=" + VmFileManager.getPath(vmConfigs.vmID, varsFile) + ",format=raw,if=pflash";
} else {
bios = "-bios ";
bios += AppConfig.basefiledir + "bios-vectras.bin";
}
extractFirmware(activity);
}
// String machine = "-M ";
// if (Objects.equals(MainSettingsManager.getArch(activity), "X86_64")) {
// machine += "pc";
// params.add(machine);
// } else if (Objects.equals(MainSettingsManager.getArch(activity), "ARM64")) {
// machine += "virt";
// params.add(machine);
// }
// This is the default in Qemu, so no need to set it.
// if (MainSettingsManager.useMemoryOvercommit(activity)) {
// params.add("-overcommit");
// params.add("mem-lock=off");
// }
if (vmConfigs.isUseLocalTime) {
params.add("-rtc");
params.add("base=localtime");
}
//if (!MainSettingsManager.getArch(activity).equals("PPC")) {
//params.add("-nodefaults");
//}
//if (!Objects.equals(MainSettingsManager.getArch(activity), "ARM64")) {
params.add(bios);
//}
// params.add(boot);
// if (!ParamManager.hasMemory(extras)) {
// String memoryStr = "-m ";
// if (MainSettingsManager.getArch(activity).equals("PPC") && RamInfo.vectrasMemory(activity) > 2048) {
// memoryStr += 2048;
// } else {
// memoryStr += RamInfo.vectrasMemory(activity);
// }
// params.add(memoryStr);
// }
if (ifType.isEmpty()) {
if (extras.contains("-drive media=cdrom,file=")) {
finalextra = extras.replace("-drive media=cdrom,file=", "-cdrom ");
}
} else {
if (extras.contains("-cdrom ")) {
finalextra = extras.replace("-cdrom ", "-drive media=cdrom,file=");
}
}
}
params.add(finalextra);

View file

@ -705,16 +705,16 @@ public class VMManager {
},
null, null);
isQemuStopedWithError = true;
// } else if (_result.contains("Couldn't connect to XServer")) {
// if (isTryAgain) {
// DialogUtils.oneDialog(_activity, _activity.getString(R.string.problem_has_been_detected), _activity.getString(R.string.x11_display_cannot_be_used_at_this_time_content) + "\n\n" + _result, R.drawable.cast_warning_24px);
// _activity.stopService(new Intent(_activity, MainService.class));
// isQemuStopedWithError = true;
// isTryAgain = false;
// } else {
// MainStartVM.startTryAgain(_activity);
// isTryAgain = true;
// }
} else if (_result.contains("Couldn't connect to XServer")) {
if (isTryAgain) {
DialogUtils.oneDialog(_activity, _activity.getString(R.string.problem_has_been_detected), _activity.getString(R.string.x11_display_cannot_be_used_at_this_time_content) + "\n\n" + _result, R.drawable.cast_warning_24px);
_activity.stopService(new Intent(_activity, MainService.class));
isQemuStopedWithError = true;
isTryAgain = false;
} else {
MainStartVM.startTryAgain(_activity);
isTryAgain = true;
}
} else if (_result.contains("No such file or directory")) {
//Error code: NO_SUCH_FILE_OR_DIRECTORY
DialogUtils.oneDialog(_activity, _activity.getString(R.string.problem_has_been_detected), _activity.getString(R.string.error_NO_SUCH_FILE_OR_DIRECTORY) + "\n\n" + _result, R.drawable.file_copy_24px);
@ -1176,7 +1176,7 @@ public class VMManager {
}
public static String addAudioDevWav(String vmID, String env) {
final String audioDevParam = ",audiodev=snd0 -audiodev wav,id=snd0,out.frequency=48000,path=" + VmFileManager.getAudioRaw(VectrasApp.getContext(), vmID);
final String audioDevParam = ",audiodev=audiodev" + System.currentTimeMillis() + " -audiodev wav,id=audiodev" + System.currentTimeMillis() + ",out.frequency=48000,path=" + VmFileManager.getAudioRaw(VectrasApp.getContext(), vmID);
String result = env;
if (env.startsWith("-device hda-duplex ") || env.contains(" -device hda-duplex ") || env.endsWith(" -device hda-duplex")) {
result = result.replaceFirst(" -device hda-duplex", " -device hda-duplex" + audioDevParam);

View file

@ -143,7 +143,7 @@ public class LogsAdapter extends RecyclerView.Adapter<LogsAdapter.logViewHolder>
LogItem logItem = currentLevelEntries.get(position);
String msg = logItem.getString(mContext);
String time = getTime(logItem, mTimeFormat);
text = (!time.isEmpty() ? String.format("[%s] ", time) : "") + msg;
text = (!time.isEmpty() ? String.format("%s | ", time) : "") + msg;
if (forceLightText) viewHolder.textLog.setTextColor(android.graphics.Color.WHITE);
viewHolder.textLog.setText(Html.fromHtml(text));
} catch (Exception e) {

View file

@ -33,6 +33,7 @@ import com.vectras.vm.creator.configs.ListManager;
import com.vectras.vm.creator.editor.AdvancedConfigsDialog;
import com.vectras.vm.creator.editor.BoardConfigsDialog;
import com.vectras.vm.creator.editor.NetworkConfigsDialog;
import com.vectras.vm.creator.editor.SoundConfigsDialog;
import com.vectras.vm.creator.utils.CreatorUtils;
import com.vectras.vm.creator.editor.FirmwareConfigsDialog;
import com.vectras.vm.creator.editor.StorageConfigsDialog;
@ -235,6 +236,15 @@ public class VMCreatorActivity extends AppCompatActivity {
dialog.show(getSupportFragmentManager(), "network_configs_dialog");
});
binding.lnSound.setOnClickListener(v -> {
save();
SoundConfigsDialog dialog = new SoundConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "sound_configs_dialog");
});
binding.lnAdvanced.setOnClickListener(v -> {
save();
@ -473,7 +483,7 @@ public class VMCreatorActivity extends AppCompatActivity {
}
ArrayList<HashMap<String, Object>> listCpuCores = ListManager.cores(MainSettingsManager.getArch(this));
if (current.cores > listCpuCores.size() - 1)
if (current.cores >= listCpuCores.size())
current.cores = listCpuCores.size() - 1;
if (current.itemIcon != null && !current.itemIcon.isEmpty()) {
@ -527,16 +537,22 @@ public class VMCreatorActivity extends AppCompatActivity {
String currentArch = MainSettingsManager.getArch(this);
if (currentArch.equals(MainSettingsManager.X86_64_ARCH)) {
current.cores = Math.min(1, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
} else if (currentArch.equals(MainSettingsManager.ARM64_ARCH)) {
current.cores = Math.min(2, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
current.nvirt = true;
switch (currentArch) {
case MainSettingsManager.X86_64_ARCH ->
current.cores = Math.min(1, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
case MainSettingsManager.ARM64_ARCH -> {
current.cores = Math.min(2, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
current.nvirt = true;
}
case MainSettingsManager.PPC_ARCH -> current.cores = 0;
}
current.memory = 512;
current.networkCard = 3; // Intel E1000 (82540EM)
// ENSONIQ AudioPCI ES1370 : Intel HD Audio Controller (ich6)
current.soundCard = currentArch.equals(MainSettingsManager.PPC_ARCH) ? 5 : 2;
}
private void checkVMID() {

View file

@ -251,4 +251,17 @@ public class ListManager {
UniversalPickerDialog.putToList(list, 8192);
return list;
}
public static ArrayList<HashMap<String, Object>> soundCards(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.none), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_hd_audio_controller_ich9), "ich9-intel-hda");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_hd_audio_controller_ich6), "intel-hda");
UniversalPickerDialog.putToList(list, context.getString(R.string.crystal_semiconductor_cs4231a), "cs4231a");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_82801aa_ac97_audio), "ac97");
UniversalPickerDialog.putToList(list, context.getString(R.string.ensoniq_audiopci_es1370), "ES1370");
UniversalPickerDialog.putToList(list, context.getString(R.string.creative_sound_blaster_16), "sb16");
UniversalPickerDialog.putToList(list, context.getString(R.string.yamaha_ym3812_opl2), "adlib");
return list;
}
}

View file

@ -104,7 +104,7 @@ public class FirmwareConfigsDialog extends BottomSheetDialogFragment {
binding.cbvUselocaltime.setOnCheckedChangeListener((v, isChecked) -> configs.isUseLocalTime = isChecked);
if (!MainSettingsManager.getArch(requireContext()).equals("X86_64")) {
if (!MainSettingsManager.getArch(requireContext()).equals(MainSettingsManager.X86_64_ARCH) && !MainSettingsManager.getArch(requireContext()).equals(MainSettingsManager.I386_ARCH)) {
binding.cbvUseuefi.setVisibility(View.GONE);
binding.cbvUseDefaultBios.setBackground(AppCompatResources.getDrawable(requireContext(), R.drawable.object_shape_single_high));
} else {

View file

@ -0,0 +1,113 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorNetworkDialogBinding;
import com.vectras.vm.databinding.CreatorSoundDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class SoundConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "SoundConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorSoundDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
if (savedInstanceState == null) DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorSoundDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
NetworkConfigsDialogCallback callback;
public void setOnDismiss(NetworkConfigsDialogCallback callback) {
this.callback = callback;
}
public interface NetworkConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
// Auto save.
public void onPause() {
super.onPause();
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.sbvCardType.setOnClickListener(v -> VMCreatorSelector.soundCard(requireActivity(), configs.soundCard, ((position, name, value) -> {
configs.soundCard = position;
binding.sbvCardType.setSubtitle(name);
})));
load();
}
private void load() {
if (!isAdded()) return;
binding.sbvCardType.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getSoundCard(requireActivity(), configs.soundCard).get("name")).toString());
}
private void save() {
}
}

View file

@ -55,13 +55,21 @@ public class VMCreatorSelector {
}
public static void networkCard(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.networkCards(activity), position, callback, activity.getString(R.string.network_card));
showDialog(activity, ListManager.networkCards(activity), position, callback, activity.getString(R.string.cards));
}
public static HashMap<String, Object> getNetworkCard(Context context, int position) {
return ListManager.networkCards(context).get(position);
}
public static void soundCard(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.soundCards(activity), position, callback, activity.getString(R.string.cards));
}
public static HashMap<String, Object> getSoundCard(Context context, int position) {
return ListManager.soundCards(context).get(position);
}
public static HashMap<String, Object> getBootFrom(Context context, int position) {
return ListManager.bootFrom(context).get(position);
}

View file

@ -291,7 +291,7 @@ public class FilePickerDialog extends DialogFragment {
case ".conf", ".ini" -> CONFIG_FILE;
case ".zip", ".7z", ".rar" -> ZIP_FILE;
case ".java", ".kt", ".js", ".py", ".c", ".cpp", ".h", ".xml", ".html", ".css", ".lua", ".go", ".asl" -> DEV_FILE;
case ".dll" -> SYSTEM_FILE;
case ".dll", ".fd" -> SYSTEM_FILE;
case ".deb", ".rpm" -> PACKAGE_FILE;
case ".ttf", ".otf" -> FONT_FILE;
case ".jks" -> KEY_FILE;

View file

@ -535,8 +535,8 @@ public class MainActivity extends AppCompatActivity implements RomStoreFragment.
startActivity(intent);
} else if (id == R.id.navigation_qemu_doc) {
Intent intent = new Intent();
if (FileUtils.isFileExists(getFilesDir().getPath() + "/distro/usr/local/share/qemu/doc/index.html")) {
intent.putExtra("url", "file://" + getFilesDir().getPath() + "/distro/usr/local/share/qemu/doc/index.html");
if (FileUtils.isFileExists(getFilesDir().getPath() + "/distro/usr/local/share/doc/qemu/index.html")) {
intent.putExtra("url", "file://" + getFilesDir().getPath() + "/distro/usr/local/share/doc/qemu/index.html");
intent.setClass(this, WebViewActivity.class);
} else {
intent.setAction(ACTION_VIEW);

View file

@ -17,6 +17,7 @@ import com.vectras.vm.R;
import com.vectras.vm.VectrasApp;
import com.vectras.vm.core.ShellExecutor;
import com.vectras.vm.core.TermuxX11;
import com.vectras.vm.main.MainActivity;
import com.vectras.vm.setupwizard.SetupFeatureCore;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
@ -118,12 +119,12 @@ public class DisplaySystem {
null
);
} else {
if (!isUseBuiltInX11() ) {
if (!PackageUtils.isInstalled("com.termux.x11", context)) {
DialogUtils.needInstallTermuxX11(context);
return;
}
if (!PackageUtils.isInstalled("com.termux.x11", context)) {
DialogUtils.needInstallTermuxX11(context);
return;
}
if (!isUseBuiltInX11()) {
Log.d(TAG, "launchX11: Opened: com.termux.x11.MainActivity.");
Intent intent = new Intent();
intent.setClassName("com.termux.x11", "com.termux.x11.MainActivity");
@ -133,7 +134,10 @@ public class DisplaySystem {
startTermuxX11(context);
} else {
context.startActivity(new Intent(context, X11Activity.class));
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.setClass(context, X11Activity.class);
context.startActivity(intent);
}
startDesktop(context);
}

View file

@ -165,7 +165,7 @@ public class MainStartVM {
if (MainSettingsManager.getVmUi(context).equals("X11") && !VMManager.isVMRunning(context, vmID)) {
if (MainSettingsManager.getRunQemuWithXterm(context)) {
String logFilePath = VmFileManager.getLog(context, vmID);
runCommandFormat = String.format(runCommandFormat, "mkdir -p \"" + new File(logFilePath).getParent() + "\"; echo \"\" > " + logFilePath + "; xterm -e bash -c \"%s 2>&1 | tee " + logFilePath + "\"; cat " + logFilePath + "; rm " + logFilePath);
runCommandFormat = String.format(runCommandFormat, "mkdir -p \"" + new File(logFilePath).getParent() + "\"; xterm -e bash -c \"%s 2>&1 | tee " + logFilePath + "\"; cat " + logFilePath + "; rm " + logFilePath);
} else {
runCommandFormat = String.format(runCommandFormat, "bash -c \"%s\"");
}
@ -314,9 +314,10 @@ public class MainStartVM {
) {
VMManager.isQemuStopedWithError = false;
String cleanUpCommand = " && echo \"" + TAG_FINISHED_WITHOUT_ERROR + "\"\nrm -r " + Config.getCacheVMPath(vmID);
String cleanUpCommand = " && echo '" + TAG_FINISHED_WITHOUT_ERROR + "'\nrm -r " + Config.getCacheVMPath(vmID);
String finalCommand = VMManager.addAudioDevWav(vmID, String.format(runCommandFormat, env + cleanUpCommand));
String finalCommand = VMManager.addAudioDevWav(vmID, String.format(runCommandFormat, env));
finalCommand = "echo ===== COMMAND =====\necho\necho \"" + finalCommand + "\"\necho\necho ===== LOGS =====\necho\n" + finalCommand + cleanUpCommand;
if (MainSettingsManager.getVmUi(context).equals("X11")) {
finalCommand = "export DISPLAY=:0 && " + finalCommand;

View file

@ -1,5 +1,7 @@
package com.vectras.vm.main.core;
import static android.view.View.GONE;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
@ -15,14 +17,19 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.creator.VMCreatorActivity;
import com.vectras.vm.ExportRomActivity;
import com.vectras.vm.R;
import com.vectras.vm.VMManager;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.manager.FirmwareManager;
import com.vectras.vm.manager.VmAudioManager;
import com.vectras.vm.manager.VmControllerDialog;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.settings.Minitools;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ProgressDialog;
@ -110,6 +117,50 @@ public class RomOptionsDialog {
}).start();
});
if (vmConfig.isUseDefaultBios && FirmwareManager.isAVarFileExist(VmFileManager.getPath(vmConfig.vmID)) && !VMManager.isNeedLoadMigrate()) {
v.findViewById(R.id.ln_reset_uefi_bios).setOnClickListener(v7 -> {
DialogUtils.twoDialog(
activity,
activity.getString(R.string.reset_uefi_bios),
activity.getString(R.string.reset_uefi_bios_note),
activity.getString(R.string.reset),
activity.getString(R.string.cancel),
true,
R.drawable.restore_page_24px,
true,
() -> {
ProgressDialog progressDialog = new ProgressDialog(activity);
progressDialog.show();
new Thread(() -> {
FirmwareManager.erase();
activity.runOnUiThread(() -> {
progressDialog.dismiss();
Toast.makeText(activity, activity.getString(R.string.done), Toast.LENGTH_LONG).show();
});
}).start();
},
null,
null);
bottomSheetDialog.cancel();
});
} else {
v.findViewById(R.id.ln_reset_uefi_bios).setVisibility(GONE);
}
v.findViewById(R.id.ln_show_in_folder).setOnClickListener(v6 -> {
if (MainSettingsManager.getBuiltInFilePicker(activity)) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
filePickerDialog.setHomeName(vmConfig.itemName);
filePickerDialog.setLockHome(true);
filePickerDialog.browse(activity, VmFileManager.getPath(vmConfig.vmID));
} else {
FileUtils.openFolder(activity, VmFileManager.getPath(vmConfig.vmID));
}
bottomSheetDialog.cancel();
});
v.findViewById(R.id.ln_remove).setOnClickListener(v1 -> {
VMManager.deleteVMDialog(vmConfig.itemName, position, activity);
bottomSheetDialog.cancel();

View file

@ -26,14 +26,14 @@ public class DataMainRoms {
public String itemName = "";
// Board
public int machine = 0;
public int machine;
public boolean nvirt; // Nested virtualization
public int cpu = 0;
public int cores = 0;
public int threads = 0;
public int cpu;
public int cores;
public int threads;
public int memory = 0;
public int memory;
// Dummy devices
@ -69,11 +69,15 @@ public class DataMainRoms {
// Network
public int networkCard = 0;
public int networkCard;
// Sound
public int soundCard;
// Firmware
public int bootFrom = 0;
public int bootFrom;
public boolean isShowBootMenu;
@ -94,5 +98,5 @@ public class DataMainRoms {
// Deprecated
@Deprecated
public int qmpPort = 0;
public int qmpPort;
}

View file

@ -33,7 +33,7 @@ public class BatteryEmulatorManager {
File vmTemp = new File(VmFileManager.getTempPath(context, vmId));
try {
String batteryAsl = SetupFeatureCore.readTextFromAssets(context, "roms/battery.asl");
String batteryAsl = SetupFeatureCore.readTextFromAssets(context, "asl/battery.asl");
int remainingCapacity;
int lastFullChargeCapacity = (int) (DESIGN_CAPACITY - ((double) (DESIGN_CAPACITY / 100) * (batteryCycleCount * PROPERTY_CAPACITY_DEPLETED_EACH_CYCLE)));

View file

@ -24,28 +24,44 @@ public class FirmwareManager {
if (arch.equals("ARM64")) {
if (!FileUtils.isFileExists(AppConfig.basefiledir + "QEMU_EFI.img"))
SetupFeatureCore.copyAssetToFile(context, "roms/QEMU_EFI.img", AppConfig.basefiledir + "QEMU_EFI.img");
SetupFeatureCore.copyAssetToFile(context, "firmware/QEMU_EFI.img", AppConfig.basefiledir + "QEMU_EFI.img");
if (!FileUtils.isFileExists(AppConfig.basefiledir + "QEMU_VARS.img"))
SetupFeatureCore.copyAssetToFile(context, "roms/QEMU_VARS.img", AppConfig.basefiledir + "QEMU_VARS.img");
SetupFeatureCore.copyAssetToFile(context, "firmware/QEMU_VARS.img", AppConfig.basefiledir + "QEMU_VARS.img");
} else if (arch.equals("X86_64") && (MainSettingsManager.getuseUEFI(context) || isUseUefi)) {
if (!FileUtils.isFileExists(AppConfig.basefiledir + "RELEASEX64_OVMF.fd"))
SetupFeatureCore.copyAssetToFile(context, "roms/RELEASEX64_OVMF.fd", AppConfig.basefiledir + "RELEASEX64_OVMF.fd");
if (!FileUtils.isFileExists(AppConfig.basefiledir + "edk2-x86_64-code.fd"))
SetupFeatureCore.copyAssetToFile(context, "firmware/edk2-x86_64-code.fd", AppConfig.basefiledir + "edk2-x86_64-code.fd");
if (!FileUtils.isFileExists(AppConfig.basefiledir + "RELEASEX64_OVMF_VARS.fd"))
SetupFeatureCore.copyAssetToFile(context, "roms/RELEASEX64_OVMF_VARS.fd", AppConfig.basefiledir + "RELEASEX64_OVMF_VARS.fd");
if (!FileUtils.isFileExists(AppConfig.basefiledir + "edk2-x86_64-vars.fd"))
SetupFeatureCore.copyAssetToFile(context, "firmware/edk2-x86_64-vars.fd", AppConfig.basefiledir + "edk2-x86_64-vars.fd");
} else if (arch.equals(MainSettingsManager.I386_ARCH) && (MainSettingsManager.getuseUEFI(context) || isUseUefi)) {
if (!FileUtils.isFileExists(AppConfig.basefiledir + "edk2-i386-code.fd"))
SetupFeatureCore.copyAssetToFile(context, "firmware/edk2-i386-code.fd", AppConfig.basefiledir + "edk2-i386-code.fd");
if (!FileUtils.isFileExists(AppConfig.basefiledir + "edk2-i386-vars.fd"))
SetupFeatureCore.copyAssetToFile(context, "firmware/edk2-i386-vars.fd", AppConfig.basefiledir + "edk2-i386-vars.fd");
} else {
if (!FileUtils.isFileExists(AppConfig.basefiledir + "bios-vectras.bin"))
SetupFeatureCore.copyAssetToFile(context, "roms/bios-vectras.bin", AppConfig.basefiledir + "bios-vectras.bin");
SetupFeatureCore.copyAssetToFile(context, "firmware/bios-vectras.bin", AppConfig.basefiledir + "bios-vectras.bin");
}
}
}
public static void deleteAll() {
FileUtils.delete(AppConfig.basefiledir + "bios-vectras.bin");
FileUtils.delete(AppConfig.basefiledir + "QEMU_EFI.img");
public static void erase() {
FileUtils.delete(AppConfig.basefiledir + "QEMU_VARS.img");
FileUtils.delete(AppConfig.basefiledir + "RELEASEX64_OVMF.fd");
FileUtils.delete(AppConfig.basefiledir + "RELEASEX64_OVMF_VARS.fd");
FileUtils.delete(AppConfig.basefiledir + "edk2-i386-vars.fd");
FileUtils.delete(AppConfig.basefiledir + "edk2-x86_64-vars.fd");
}
public static boolean isAVarFileExist(String folderPath) {
return FileUtils.isFileExists(AppConfig.basefiledir + "QEMU_VARS.img") ||
FileUtils.isFileExists(AppConfig.basefiledir + "edk2-i386-vars.fd") ||
FileUtils.isFileExists(AppConfig.basefiledir + "edk2-x86_64-vars.fd");
}
public static void erase(String folderPath) {
FileUtils.delete(folderPath + "QEMU_VARS.img");
FileUtils.delete(folderPath + "edk2-i386-vars.fd");
FileUtils.delete(folderPath + "edk2-x86_64-vars.fd");
}
}

View file

@ -22,10 +22,10 @@ import java.io.File;
public class ToolsManager {
public static void mount3dfxWrappers(Activity activity) {
new Thread(() -> {
if (!FileUtils.isFileExists(AppConfig.basefiledir + "3dfx-wrappers.iso"))
SetupFeatureCore.copyAssetToFile(activity, "roms/3dfx-wrappers.iso", AppConfig.basefiledir + "3dfx-wrappers.iso");
if (!FileUtils.isFileExists(AppConfig.basefiledir + "3dfx-wrappers-i686.iso"))
SetupFeatureCore.copyAssetToFile(activity, "driver/3dfx-wrappers-i686.iso", AppConfig.basefiledir + "3dfx-wrappers-i686.iso");
activity.runOnUiThread(() -> QmpSender.changeDynamicSecondaryOpticalDisc(activity, AppConfig.basefiledir + "3dfx-wrappers.iso", ""));
activity.runOnUiThread(() -> QmpSender.changeDynamicSecondaryOpticalDisc(activity, AppConfig.basefiledir + "3dfx-wrappers-i686.iso", ""));
}).start();
}

View file

@ -284,11 +284,11 @@ public class VmControllerDialog extends DialogFragment {
binding.lnSecondaryCdrom.setVisibility(View.GONE);
}
if (!infoBlock.contains(AppConfig.basefiledir + "3dfx-wrappers.iso"))
if (!infoBlock.contains(AppConfig.basefiledir + "3dfx-wrappers-i686.iso"))
binding.ivEject3dfx.setVisibility(View.GONE);
binding.ln3dfx.setOnClickListener(v -> {
if (infoBlock.contains(AppConfig.basefiledir + "3dfx-wrappers.iso")) {
if (infoBlock.contains(AppConfig.basefiledir + "3dfx-wrappers-i686.iso")) {
QmpSender.ejectDynamicSecondaryOpticalDisc(requireActivity(), infoBlock);
} else {
ToolsManager.mount3dfxWrappers(requireActivity());

View file

@ -17,7 +17,7 @@ public class WifiCardEmulatorManager {
File vmTemp = new File(VmFileManager.getTempPath(context, vmId));
try {
String wifiAsl = SetupFeatureCore.readTextFromAssets(context, "roms/wifi.asl");
String wifiAsl = SetupFeatureCore.readTextFromAssets(context, "asl/wifi.asl");
FileUtils.writeToFile(vmTemp.getAbsolutePath(), "wifi.asl", wifiAsl);

View file

@ -113,51 +113,51 @@ public class Minitools extends AppCompatActivity {
binding.reinstallsystem.setOnClickListener(v -> DialogUtils.twoDialog(Minitools.this, getResources().getString(R.string.reinstall_system), getResources().getString(R.string.reinstall_system_content), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.system_update_24px, true,
this::eraserSystem, null, null));
if (FirmwareManager.isExistOne()) {
binding.lnResetUefiBios.setOnClickListener(v -> {
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setText(getString(R.string.just_a_sec));
progressDialog.show();
new Thread(() -> {
boolean isQemuRunning = ProcessManager.isQemuRunning(this);
runOnUiThread(() -> {
progressDialog.dismiss();
if (isQemuRunning) {
DialogUtils.oopsDialog(Minitools.this, getString(R.string.need_to_shut_down_all_running_vm_note));
} else {
DialogUtils.twoDialog(
Minitools.this,
getString(R.string.reset_uefi_bios),
getString(R.string.reset_uefi_bios_note),
getString(R.string.reset),
getString(R.string.cancel),
true,
R.drawable.restore_page_24px,
true,
() -> {
progressDialog.show();
new Thread(() -> {
FirmwareManager.deleteAll();
runOnUiThread(() -> {
progressDialog.dismiss();
binding.lnResetUefiBios.setVisibility(GONE);
Toast.makeText(Minitools.this, getString(R.string.done), Toast.LENGTH_LONG).show();
});
}).start();
},
null,
null);
}
});
}).start();
});
} else {
binding.lnResetUefiBios.setVisibility(GONE);
}
// if (FirmwareManager.isExistOne()) {
// binding.lnResetUefiBios.setOnClickListener(v -> {
// ProgressDialog progressDialog = new ProgressDialog(this);
// progressDialog.setText(getString(R.string.just_a_sec));
// progressDialog.show();
//
// new Thread(() -> {
// boolean isQemuRunning = ProcessManager.isQemuRunning(this);
// runOnUiThread(() -> {
// progressDialog.dismiss();
//
// if (isQemuRunning) {
// DialogUtils.oopsDialog(Minitools.this, getString(R.string.need_to_shut_down_all_running_vm_note));
// } else {
// DialogUtils.twoDialog(
// Minitools.this,
// getString(R.string.reset_uefi_bios),
// getString(R.string.reset_uefi_bios_note),
// getString(R.string.reset),
// getString(R.string.cancel),
// true,
// R.drawable.restore_page_24px,
// true,
// () -> {
// progressDialog.show();
//
// new Thread(() -> {
// FirmwareManager.erase();
// runOnUiThread(() -> {
// progressDialog.dismiss();
//
// binding.lnResetUefiBios.setVisibility(GONE);
// Toast.makeText(Minitools.this, getString(R.string.done), Toast.LENGTH_LONG).show();
// });
// }).start();
// },
// null,
// null);
// }
// });
// }).start();
// });
// } else {
// binding.lnResetUefiBios.setVisibility(GONE);
// }
ListUtils.setupMirrorListForListmap(mirrorlist);
}

View file

@ -0,0 +1,28 @@
package com.vectras.vm.settings;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.preference.PreferenceManager;
public class SettingsData {
public static boolean alwaysShowLog(Context context) {
return get(context, "alwaysShowLog");
}
public static void alwaysShowLog(Context context, boolean value) {
set(context, "alwaysShowLog", value);
}
public static boolean get(Context context, String key) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(key, false);
}
public static void set(Context context, String key, boolean value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(key, value);
edit.apply();
}
}

View file

@ -36,8 +36,12 @@ public class SystemSettingsActivity extends AppCompatActivity {
binding.swQuickStart.setOnCheckedChangeListener((buttonView, isChecked) -> MainSettingsManager.setQuickStart(this, isChecked));
binding.lnQuickStart.setOnClickListener(v -> binding.swQuickStart.toggle());
binding.swAlwaysShowLogs.setOnCheckedChangeListener((buttonView, isChecked) -> SettingsData.alwaysShowLog(this, isChecked));
binding.lnAlwaysShowLogs.setOnClickListener(v -> binding.swAlwaysShowLogs.toggle());
binding.swCopyFile.setChecked(MainSettingsManager.copyFile(this));
binding.swQuickStart.setChecked(MainSettingsManager.getQuickStart(this));
binding.swAlwaysShowLogs.setChecked(SettingsData.alwaysShowLog(this));
binding.lnLanguage.setOnClickListener(v -> {
ItemSettingsSelector.language(this, ItemSettingsSelector.getLanguagePosition(this, MainSettingsManager.getLang(this)), (position, name, value) -> {

View file

@ -462,10 +462,26 @@ public class SetupWizard2Activity extends AppCompatActivity {
if (ACTION == ACTION_SYSTEM_UPDATE) {
cmd += "echo \"Uninstalling...\";" +
"set +e;" +
" rm -f /usr/local/bin/elf2dmp;" +
" rm -f /usr/local/bin/qemu-*;" +
" rm -f /usr/share/applications/qemu.desktop;" +
" rm -f /usr/share/icons/hicolor/*/qemu.png;" +
" rm -rf /usr/share/qemu;" +
" rm -f /usr/local/include/qemu-*;" +
" rm -f /usr/local/libexec/qemu-*;" +
" rm -f /usr/local/libexec/vhost-user-gpu;" +
" rm -f /usr/local/libexec/virtfs-proxy-helper;" +
" rm -f /usr/local/libexec/virtiofsd;" +
" rm -rf /usr/local/share/doc/qemu;" +
" rm -f /usr/local/share/applications/qemu.desktop;" +
" rm -f /usr/local/share/icons/hicolor/*/qemu.png;" +
" rm -f /usr/local/share/locale/*/qemu.mo;" +
" rm -f /usr/local/share/man/man1/qemu*;" +
" rm -f /usr/local/share/man/man1/virtfs-proxy-helper.1;" +
" rm -f /usr/local/share/man/man1/virtiofsd.1;" +
" rm -f /usr/local/share/man/man7/qemu*;" +
" rm -f /usr/local/share/man/man8/qemu*;" +
" rm -rf /usr/local/share/qemu;" +
" set -e;" +
" echo \"Downloading Qemu...\";" +
downloadBootstrapsCommand + ";" +
" echo \"Installing Qemu...\";" +
" tar -xzvf setup.tar.gz -C /;" +

View file

@ -97,7 +97,7 @@ public class TurnipZinkSetupWizardActivity extends AppCompatActivity {
return;
}
if (FileUtils.isFileExists(AppConfig.internalDataDirPath + "/distro/usr/share/drirc.d/00-mesa-defaults.conf")) {
if (FileUtils.isFileExists(AppConfig.internalDataDirPath + "/distro/usr/lib/dri/zink_dri.so")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> uiControllder(STEP_INSTALLED), 1000);
return;
}
@ -169,7 +169,7 @@ public class TurnipZinkSetupWizardActivity extends AppCompatActivity {
if (isFinishing() || isDestroyed()) return;
runOnUiThread(() -> {
if (log.contains(COMPLETED_MARK) && FileUtils.isFileExists(AppConfig.internalDataDirPath + "/distro/usr/share/drirc.d/00-mesa-defaults.conf")) {
if (log.contains(COMPLETED_MARK) && FileUtils.isFileExists(AppConfig.internalDataDirPath + "/distro/usr/lib/dri/zink_dri.so")) {
uiControllder(STEP_INSTALLED);
} else {
logs = log;

View file

@ -39,6 +39,8 @@ import androidx.core.content.FileProvider;
import androidx.documentfile.provider.DocumentFile;
import com.vectras.vm.R;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.manager.VmFileManager;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@ -899,17 +901,24 @@ public class FileUtils {
try {
context.startActivity(intent);
} catch (Exception e) {
DialogUtils.oneDialog(
context,
context.getString(R.string.oops),
context.getString(R.string.there_is_no_app_to_perform_this_action),
context.getString(R.string.ok),
true,
R.drawable.error_96px,
true,
null,
null
);
if (context instanceof Activity activity) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
filePickerDialog.setLockHome(true);
filePickerDialog.browse(activity, folderPath);
} else {
DialogUtils.oneDialog(
context,
context.getString(R.string.oops),
context.getString(R.string.there_is_no_app_to_perform_this_action),
context.getString(R.string.ok),
true,
R.drawable.error_96px,
true,
null,
null
);
}
Log.e(TAG, "openFolder: " + e.getMessage());
}
}

View file

@ -165,26 +165,26 @@
android:text="@string/delete_all" />
</LinearLayout>
<LinearLayout
android:id="@+id/ln_reset_uefi_bios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:background="@drawable/object_shape_middle_high"
android:gravity="center_vertical"
android:padding="16dp">
<!-- <LinearLayout-->
<!-- android:id="@+id/ln_reset_uefi_bios"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="2dp"-->
<!-- android:background="@drawable/object_shape_middle_high"-->
<!-- android:gravity="center_vertical"-->
<!-- android:padding="16dp">-->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/restore_page_24px" />
<!-- <ImageView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:src="@drawable/restore_page_24px" />-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="@string/reset_uefi_bios" />
</LinearLayout>
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginLeft="8dp"-->
<!-- android:text="@string/reset_uefi_bios" />-->
<!-- </LinearLayout>-->
<LinearLayout
android:id="@+id/reinstallsystem"

View file

@ -123,6 +123,48 @@
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_always_show_logs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/sw_always_show_logs"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/always_show_logs"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/always_show_logs_setting_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_always_show_logs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_language"
android:layout_width="match_parent"

View file

@ -258,6 +258,38 @@
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_sound"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sound"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sound_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_firmware"
android:layout_width="match_parent"

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="true"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/sound" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_card_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/card_type"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_single_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -147,6 +147,52 @@
android:text="@string/clean_up"/>
</LinearLayout>
<LinearLayout
android:id="@+id/ln_reset_uefi_bios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingVertical="8dp"
android:paddingHorizontal="16dp"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/restore_page_24px"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:padding="8dp"
android:textColor="?attr/colorControlNormal"
android:text="@string/reset_uefi_bios"/>
</LinearLayout>
<LinearLayout
android:id="@+id/ln_show_in_folder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingVertical="8dp"
android:paddingHorizontal="16dp"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/folder_open_24px"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:padding="8dp"
android:textColor="?attr/colorControlNormal"
android:text="@string/show_in_folder"/>
</LinearLayout>
<LinearLayout
android:id="@+id/ln_remove"
android:layout_width="match_parent"

View file

@ -605,7 +605,7 @@
<string name="filters">Các bộ lọc</string>
<string name="filters_settings_note">Tìm kiếm với nhiều sự kiểm soát hơn và duyệt nhanh hơn.</string>
<string name="reset_uefi_bios">Đặt lại UEFI/BIOS</string>
<string name="reset_uefi_bios_note">Tất cả các cài đặt của UEFI/BIOS mặc định sẽ được đặt lại. Bạn có muốn tiếp tục?</string>
<string name="reset_uefi_bios_note">Tất cả các cài đặt của UEFI/BIOS sẽ được đặt lại. Bạn có muốn tiếp tục?</string>
<string name="need_to_shut_down_all_running_vm_note">Bạn cần tắt tất cả máy ảo đang chạy để thực hiện hành động này.</string>
<string name="auto_switch_to_external_mouse">Tự động chuyển sang chuột ngoài</string>
<string name="auto_switch_to_external_mouse_note">Tự động chuyển đổi khi kết nối và ngắt chuột rời.</string>
@ -671,6 +671,11 @@
<string name="your_device_does_not_meet_the_requirements_to_continue">Thiết bị của bạn không đáp ứng đủ các điều kiện để tiếp tục.</string>
<string name="error_in_core_feature_content">Một tính năng cốt lõi của ứng dụng vừa xảy ra sự cố. Bạn có thể cần đóng ứng dụng và mở lại để các tính năng hoạt động bình thường trở lại.</string>
<string name="force_stop">Buộc dừng</string>
<string name="sound">Ấm thanh</string>
<string name="sound_note">Thẻ âm thanh,…</string>
<string name="cards">Các thẻ</string>
<string name="always_show_logs">Luôn hiện nhật ký</string>
<string name="always_show_logs_setting_note">Hộp thoại hiển thị nhật ký sẽ xuất hiện dù máy ảo không có sự cố nghiêm trọng nào xảy ra sau khi tắt nguồn.</string>
<!--======================TERMUX STRINGS====================-->
<string name="application_name" translatable="false">Vterm</string>

View file

@ -623,7 +623,7 @@
<string name="filters">Filters</string>
<string name="filters_settings_note">Search with more control and browse faster.</string>
<string name="reset_uefi_bios">Reset UEFI/BIOS</string>
<string name="reset_uefi_bios_note">All default UEFI/BIOS settings will be reset. Do you want to continue?</string>
<string name="reset_uefi_bios_note">All UEFI/BIOS settings will be reset. Do you want to continue?</string>
<string name="need_to_shut_down_all_running_vm_note">You need to shut down all running virtual machines to perform this action.</string>
<string name="auto_switch_to_external_mouse">Auto switch to external mouse</string>
<string name="auto_switch_to_external_mouse_note">Automatically switches when the mouse is connected and disconnected.</string>
@ -692,6 +692,11 @@
<string name="your_device_does_not_meet_the_requirements_to_continue">Your device does not meet the requirements to continue.</string>
<string name="error_in_core_feature_content">A core feature of the app has just experienced an issue. You may need to close and reopen the app for the features to work properly again.</string>
<string name="force_stop">Force stop</string>
<string name="sound">Sound</string>
<string name="sound_note">Sound card,...</string>
<string name="cards">Cards</string>
<string name="always_show_logs">Always show logs</string>
<string name="always_show_logs_setting_note">The log display dialog will appear even if no serious problems occurred with the virtual machine after it was powered off.</string>
@ -1057,6 +1062,15 @@ E.g. <b>META</b> for <i>META key</i>, \n
<string name="amigaone" translatable="false">Eyetech AmigaOne</string>
<string name="sam460ex" translatable="false">aCube Sam460ex</string>
<!-- Sound cards -->
<string name="intel_hd_audio_controller_ich9" translatable="false">Intel HD Audio Controller (ich9)</string>
<string name="intel_hd_audio_controller_ich6" translatable="false">Intel HD Audio Controller (ich6)</string>
<string name="crystal_semiconductor_cs4231a" translatable="false">Crystal Semiconductor CS4231A</string>
<string name="intel_82801aa_ac97_audio" translatable="false">Intel 82801AA AC97 Audio</string>
<string name="ensoniq_audiopci_es1370" translatable="false">ENSONIQ AudioPCI ES1370</string>
<string name="creative_sound_blaster_16" translatable="false">Creative Sound Blaster 16</string>
<string name="yamaha_ym3812_opl2" translatable="false">Yamaha YM3812 (OPL2)</string>
<!-- Feature: User Profile -->
<!-- Feature: Settings -->

View file

@ -37,10 +37,23 @@ pkill -9 -f qemu-system- || true
clear
echo -e "\e[1;37m[i] Uninstalling current Qemu..."
rm -f /usr/local/bin/elf2dmp
rm -f /usr/local/bin/qemu-*
rm -f /usr/share/applications/qemu.desktop
rm -f /usr/share/icons/hicolor/*/qemu.png
rm -rf /usr/share/qemu
rm -f /usr/local/include/qemu-*
rm -f /usr/local/libexec/qemu-*
rm -f /usr/local/libexec/vhost-user-gpu
rm -f /usr/local/libexec/virtfs-proxy-helper
rm -f /usr/local/libexec/virtiofsd
rm -rf /usr/local/share/doc/qemu
rm -f /usr/local/share/applications/qemu.desktop
rm -f /usr/local/share/icons/hicolor/*/qemu.png
rm -f /usr/local/share/locale/*/qemu.mo
rm -f /usr/local/share/man/man1/qemu*
rm -f /usr/local/share/man/man1/virtfs-proxy-helper.1
rm -f /usr/local/share/man/man1/virtiofsd.1
rm -f /usr/local/share/man/man7/qemu*
rm -f /usr/local/share/man/man8/qemu*
rm -rf /usr/local/share/qemu
clear
echo -e "\e[1;37m[i] Downloading..."

View file

@ -1,17 +1,24 @@
#!/bin/bash
clear
unset qemuurl
architecture=$(uname -m)
if [[ ! "$architecture" =~ "aarch64" ]]; then
rm -f setup.sh
if [[ "$architecture" =~ "aarch64" ]]; then
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-arm64-v8a.tar.gz"
elif [[ "$architecture" =~ "x86_64" ]]; then
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-x86_64.tar.gz"
fi
if [[ -z "$qemuurl" ]]; then
echo -e "\e[1;37m[!] Unsupported architecture!"
echo -e "\e[1;37m-\e[0m"
echo -e "\e[1;37mYour device's is not supported. Your device needs to be AArch64 to install this version of Qemu."
echo -e "\e[1;37mYour device's is not supported."
echo -e "\e[1;37m-\e[0m"
echo -e "\e[1;37mSetup was canceled."
rm -f setup.sh
exit
fi
echo -e "\e[1;37m[!] Qemu 7.2.22 upgrade tool. Warning and do not ignore!"
echo -e "\e[1;37m[!] Qemu 7.2.2 upgrade tool. Warning and do not ignore!"
echo -e "\e[1;37m-\e[0m"
echo -e "\e[1;37mPlease do not run any other commands when this setup begins. If you're running other commands, they haven't finished executing yet or don't want some packages to be forced to be updated when setting up. Any existing installed version of Qemu will be uninstalled. Press Ctrl + C now to cancel the setup immediately."
echo -e "\e[1;37m\e[0m"
@ -27,7 +34,7 @@ clear
echo -e "\e[1;37m[i] Installing packages..."
apk update
apk add perl aria2
apk add aria2
clear
echo -e "\e[1;37m[i] Killing process..."
@ -37,14 +44,27 @@ pkill -9 -f qemu-system- || true
clear
echo -e "\e[1;37m[i] Uninstalling current Qemu..."
rm -f /usr/local/bin/elf2dmp
rm -f /usr/local/bin/qemu-*
rm -f /usr/share/applications/qemu.desktop
rm -f /usr/share/icons/hicolor/*/qemu.png
rm -rf /usr/share/qemu
rm -f /usr/local/include/qemu-*
rm -f /usr/local/libexec/qemu-*
rm -f /usr/local/libexec/vhost-user-gpu
rm -f /usr/local/libexec/virtfs-proxy-helper
rm -f /usr/local/libexec/virtiofsd
rm -rf /usr/local/share/doc/qemu
rm -f /usr/local/share/applications/qemu.desktop
rm -f /usr/local/share/icons/hicolor/*/qemu.png
rm -f /usr/local/share/locale/*/qemu.mo
rm -f /usr/local/share/man/man1/qemu*
rm -f /usr/local/share/man/man1/virtfs-proxy-helper.1
rm -f /usr/local/share/man/man1/virtiofsd.1
rm -f /usr/local/share/man/man7/qemu*
rm -f /usr/local/share/man/man8/qemu*
rm -rf /usr/local/share/qemu
clear
echo -e "\e[1;37m[i] Downloading..."
aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-june-2026-vectras-vm-arm64-v8a.tar.gz
aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz "$qemuurl"
clear
echo -e "\e[1;37m[i] Installing..."

View file

@ -3,9 +3,9 @@ clear
unset qemuurl
architecture=$(uname -m)
if [[ "$architecture" =~ "aarch64" ]]; then
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.1.1/base-may-2026-vectras-vm-arm64-v8a.tar.gz"
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-9.2.2-3dfx-july-2026-vectras-vm-arm64-v8a.tar.gz"
elif [[ "$architecture" =~ "x86_64" ]]; then
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.1/base-generic-vectras-vm-x86_64.tar.gz"
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-9.2.2-3dfx-july-2026-vectras-vm-x86_64.tar.gz"
elif [[ "$architecture" =~ "arm" ]]; then
qemuurl="https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.4/base-vectras-vm-armeabi-v7a.tar.gz"
elif [[ "$architecture" =~ "x86" ]]; then
@ -50,10 +50,23 @@ pkill -9 -f qemu-system- || true
clear
echo -e "\e[1;37m[i] Uninstalling current Qemu..."
rm -f /usr/local/bin/elf2dmp
rm -f /usr/local/bin/qemu-*
rm -f /usr/share/applications/qemu.desktop
rm -f /usr/share/icons/hicolor/*/qemu.png
rm -rf /usr/share/qemu
rm -f /usr/local/include/qemu-*
rm -f /usr/local/libexec/qemu-*
rm -f /usr/local/libexec/vhost-user-gpu
rm -f /usr/local/libexec/virtfs-proxy-helper
rm -f /usr/local/libexec/virtiofsd
rm -rf /usr/local/share/doc/qemu
rm -f /usr/local/share/applications/qemu.desktop
rm -f /usr/local/share/icons/hicolor/*/qemu.png
rm -f /usr/local/share/locale/*/qemu.mo
rm -f /usr/local/share/man/man1/qemu*
rm -f /usr/local/share/man/man1/virtfs-proxy-helper.1
rm -f /usr/local/share/man/man1/virtiofsd.1
rm -f /usr/local/share/man/man7/qemu*
rm -f /usr/local/share/man/man8/qemu*
rm -rf /usr/local/share/qemu
clear
echo -e "\e[1;37m[i] Downloading..."

View file

@ -44,10 +44,23 @@ pkill -9 -f qemu-system- || true
clear
echo -e "\e[1;37m[i] Uninstalling current Qemu..."
rm -f /usr/local/bin/elf2dmp
rm -f /usr/local/bin/qemu-*
rm -f /usr/share/applications/qemu.desktop
rm -f /usr/share/icons/hicolor/*/qemu.png
rm -rf /usr/share/qemu
rm -f /usr/local/include/qemu-*
rm -f /usr/local/libexec/qemu-*
rm -f /usr/local/libexec/vhost-user-gpu
rm -f /usr/local/libexec/virtfs-proxy-helper
rm -f /usr/local/libexec/virtiofsd
rm -rf /usr/local/share/doc/qemu
rm -f /usr/local/share/applications/qemu.desktop
rm -f /usr/local/share/icons/hicolor/*/qemu.png
rm -f /usr/local/share/locale/*/qemu.mo
rm -f /usr/local/share/man/man1/qemu*
rm -f /usr/local/share/man/man1/virtfs-proxy-helper.1
rm -f /usr/local/share/man/man1/virtiofsd.1
rm -f /usr/local/share/man/man7/qemu*
rm -f /usr/local/share/man/man8/qemu*
rm -rf /usr/local/share/qemu
clear
echo -e "\e[1;37m[i] Downloading..."

View file

@ -1,7 +1,7 @@
{
"aarch64":"https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.1.1/base-may-2026-vectras-vm-arm64-v8a.tar.gz",
"armhf": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.4/base-vectras-vm-armeabi-v7a.tar.gz",
"amd64":"https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.1/base-generic-vectras-vm-x86_64.tar.gz",
"amd64":"https://archive.org/download/qemu-9-2-2-3dfx-for-vectras-vm-nbab/base-july-2026-vectras-vm-x86_64.tar.gz",
"x86": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/3.5.4/base-vectras-vm-x86.tar.gz",
"aarch64_adreno": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.5/mesa-26.1.0-devel-20260404_alpine_3-19_aarch64.tar.gz",
"aarch64_libglvnd": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.5/libglvnd-1.7.0_alpine_3-19_aarch64.tar.gz"

View file

@ -0,0 +1,8 @@
{
"aarch64":"https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-arm64-v8a.tar.gz",
"armhf": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-july-2026-vectras-vm-armeabi-v7a.tar.gz",
"amd64":"https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-3dfx-july-2026-vectras-vm-x86_64.tar.gz",
"x86": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.7/base-qemu-7.2.22-july-2026-vectras-vm-x86.tar.gz",
"aarch64_adreno": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.5/mesa-26.1.0-devel-20260404_alpine_3-19_aarch64.tar.gz",
"aarch64_libglvnd": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/download/4.4.5/libglvnd-1.7.0_alpine_3-19_aarch64.tar.gz"
}