mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 03:02:22 +01:00
Added nullrhi option
This commit is contained in:
Binary file not shown.
@@ -36,15 +36,16 @@ class GameController extends GetxController {
|
|||||||
_selectedVersion = Rxn(decodedSelectedVersion);
|
_selectedVersion = Rxn(decodedSelectedVersion);
|
||||||
|
|
||||||
host = RxBool(_storage.read("host") ?? false);
|
host = RxBool(_storage.read("host") ?? false);
|
||||||
|
host.listen((value) {
|
||||||
|
_storage.write("host", value);
|
||||||
|
username.text = _storage.read("${host.value ? 'host' : 'game'}_username") ?? "";
|
||||||
|
});
|
||||||
|
|
||||||
username = TextEditingController(text: _storage.read("${host.value ? 'host' : 'game'}_username") ?? "");
|
username = TextEditingController(text: _storage.read("${host.value ? 'host' : 'game'}_username") ?? "");
|
||||||
username.addListener(() async {
|
username.addListener(() async {
|
||||||
await _storage.write("${host.value ? 'host' : 'game'}_username", username.text);
|
await _storage.write("${host.value ? 'host' : 'game'}_username", username.text);
|
||||||
});
|
});
|
||||||
|
|
||||||
host.listen((value) => _storage.write("host", value));
|
|
||||||
host.listen((value) => username.text = _storage.read("${host.value ? 'host' : 'game'}_username") ?? "");
|
|
||||||
|
|
||||||
started = RxBool(false);
|
started = RxBool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,33 +12,29 @@ class FortniteVersion {
|
|||||||
|
|
||||||
FortniteVersion({required this.name, required this.location});
|
FortniteVersion({required this.name, required this.location});
|
||||||
|
|
||||||
static File findExecutable(Directory directory, String name) {
|
static File? findExecutable(Directory directory, String name) {
|
||||||
if(path.basename(directory.path) == "FortniteGame"){
|
|
||||||
return File("$directory/Binaries/Win64/$name");
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
var gameDirectory = directory.listSync(recursive: true)
|
var result = directory.listSync(recursive: true)
|
||||||
.firstWhereOrNull((element) => path.basename(element.path) == "FortniteGame");
|
.firstWhereOrNull((element) => path.basename(element.path) == name);
|
||||||
if(gameDirectory == null){
|
if(result == null){
|
||||||
return File("${directory.path}/Binaries/Win64/$name");
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return File("${gameDirectory.path}/Binaries/Win64/$name");
|
return File(result.path);
|
||||||
}catch(_){
|
}catch(_){
|
||||||
return File("${directory.path}/Binaries/Win64/$name");
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File get executable {
|
File? get executable {
|
||||||
return findExecutable(location, "FortniteClient-Win64-Shipping.exe");
|
return findExecutable(location, "FortniteClient-Win64-Shipping.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
File get launcher {
|
File? get launcher {
|
||||||
return findExecutable(location, "FortniteLauncher.exe");
|
return findExecutable(location, "FortniteLauncher.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
File get eacExecutable {
|
File? get eacExecutable {
|
||||||
return findExecutable(location, "FortniteClient-Win64-Shipping_EAC.exe");
|
return findExecutable(location, "FortniteClient-Win64-Shipping_EAC.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class InfoPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const Expanded(
|
const Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.bottomLeft, child: Text("Version 3.6${kDebugMode ? '-DEBUG' : ''}")))
|
alignment: Alignment.bottomLeft, child: Text("Version 3.7${kDebugMode ? '-DEBUG' : ''}")))
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Future<bool> injectDll(int pid, String dll) async {
|
|||||||
var process = await shell.run("./injector.exe -p $pid --inject \"$dll\"");
|
var process = await shell.run("./injector.exe -p $pid --inject \"$dll\"");
|
||||||
var success = process.outText.contains("Successfully injected module");
|
var success = process.outText.contains("Successfully injected module");
|
||||||
if (!success) {
|
if (!success) {
|
||||||
injectLogFile.writeAsString(process.outText, mode: FileMode.append);
|
injectLogFile.writeAsString(process.outText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
|||||||
40
lib/src/util/patcher.dart
Normal file
40
lib/src/util/patcher.dart
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
final Uint8List _original = Uint8List.fromList([
|
||||||
|
45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 115, 0, 101, 0, 115, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0, 45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 102, 0, 114, 0, 111, 0, 109, 0, 32, 0, 45, 0, 112, 0, 97, 0, 114, 0, 116, 0, 121, 0, 95, 0, 106, 0, 111, 0, 105, 0, 110, 0, 105, 0, 110, 0, 102, 0, 111, 0, 95, 0, 116, 0, 111, 0, 107, 0, 101, 0, 110, 0, 32, 0, 45, 0, 114, 0, 101, 0, 112, 0, 108, 0, 97, 0, 121, 0
|
||||||
|
]);
|
||||||
|
|
||||||
|
final Uint8List _patched = Uint8List.fromList([
|
||||||
|
45, 0, 108, 0, 111, 0, 103, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 112, 0, 108, 0, 97, 0, 115, 0, 104, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 111, 0, 117, 0, 110, 0, 100, 0, 32, 0, 45, 0, 110, 0, 117, 0, 108, 0, 108, 0, 114, 0, 104, 0, 105, 0, 32, 0, 45, 0, 117, 0, 115, 0, 101, 0, 111, 0, 108, 0, 100, 0, 105, 0, 116, 0, 101, 0, 109, 0, 99, 0, 97, 0, 114, 0, 100, 0, 115, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0
|
||||||
|
]);
|
||||||
|
|
||||||
|
Future<bool> patchExe(File file) async {
|
||||||
|
if(_original.length != _patched.length){
|
||||||
|
throw Exception("Cannot mutate length of binary file");
|
||||||
|
}
|
||||||
|
|
||||||
|
var read = await file.readAsBytes();
|
||||||
|
var length = await file.length();
|
||||||
|
var offset = 0;
|
||||||
|
var counter = 0;
|
||||||
|
while(offset < length){
|
||||||
|
if(read[offset] == _original[counter]){
|
||||||
|
counter++;
|
||||||
|
}else {
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
if(counter == _original.length){
|
||||||
|
for(var index = 0; index < _patched.length; index++){
|
||||||
|
read[offset - counter + index] = _patched[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
await file.writeAsBytes(read, mode: FileMode.write);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -98,7 +98,7 @@ class AddLocalVersion extends StatelessWidget {
|
|||||||
return "Directory doesn't exist";
|
return "Directory doesn't exist";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FortniteVersion.findExecutable(directory, "FortniteClient-Win64-Shipping.exe").existsSync()) {
|
if (FortniteVersion.findExecutable(directory, "FortniteClient-Win64-Shipping.exe") == null) {
|
||||||
return "Invalid game path";
|
return "Invalid game path";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:reboot_launcher/src/controller/game_controller.dart';
|
|||||||
import 'package:reboot_launcher/src/controller/server_controller.dart';
|
import 'package:reboot_launcher/src/controller/server_controller.dart';
|
||||||
import 'package:reboot_launcher/src/util/injector.dart';
|
import 'package:reboot_launcher/src/util/injector.dart';
|
||||||
import 'package:reboot_launcher/src/util/binary.dart';
|
import 'package:reboot_launcher/src/util/binary.dart';
|
||||||
|
import 'package:reboot_launcher/src/util/patcher.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:win32_suspend_process/win32_suspend_process.dart';
|
import 'package:win32_suspend_process/win32_suspend_process.dart';
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
child: Obx(() => Tooltip(
|
child: Obx(() => Tooltip(
|
||||||
message: _gameController.started.value ? "Close the running Fortnite instance" : "Launch a new Fortnite instance",
|
message: _gameController.started.value ? "Close the running Fortnite instance" : "Launch a new Fortnite instance",
|
||||||
child: Button(
|
child: Button(
|
||||||
onPressed: () => _onPressed(context),
|
onPressed: _onPressed,
|
||||||
child: Text(_gameController.started.value ? "Close" : "Launch")
|
child: Text(_gameController.started.value ? "Close" : "Launch")
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
@@ -43,7 +44,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onPressed(BuildContext context) async {
|
void _onPressed() async {
|
||||||
if (_gameController.username.text.isEmpty) {
|
if (_gameController.username.text.isEmpty) {
|
||||||
showSnackbar(
|
showSnackbar(
|
||||||
context, const Snackbar(content: Text("Please type a username")));
|
context, const Snackbar(content: Text("Please type a username")));
|
||||||
@@ -84,38 +85,103 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
try {
|
try {
|
||||||
_updateServerState(true);
|
_updateServerState(true);
|
||||||
var version = _gameController.selectedVersionObs.value!;
|
var version = _gameController.selectedVersionObs.value!;
|
||||||
if (await version.launcher.exists()) {
|
var hosting = _gameController.host.value;
|
||||||
_gameController.launcherProcess = await Process.start(version.launcher.path, []);
|
if (version.launcher != null) {
|
||||||
|
_gameController.launcherProcess = await Process.start(version.launcher!.path, []);
|
||||||
Win32Process(_gameController.launcherProcess!.pid).suspend();
|
Win32Process(_gameController.launcherProcess!.pid).suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await version.eacExecutable.exists()) {
|
if (version.eacExecutable != null) {
|
||||||
_gameController.eacProcess = await Process.start(version.eacExecutable.path, []);
|
_gameController.eacProcess = await Process.start(version.eacExecutable!.path, []);
|
||||||
Win32Process(_gameController.eacProcess!.pid).suspend();
|
Win32Process(_gameController.eacProcess!.pid).suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
_gameController.gameProcess = await Process.start(version.executable.path, _createProcessArguments())
|
if(hosting){
|
||||||
..exitCode.then((_) => _onStop())
|
await patchExe(version.executable!);
|
||||||
|
}
|
||||||
|
|
||||||
|
_gameController.gameProcess = await Process.start(version.executable!.path, _createProcessArguments())
|
||||||
|
..exitCode.then((_) => _onEnd())
|
||||||
..outLines.forEach(_onGameOutput);
|
..outLines.forEach(_onGameOutput);
|
||||||
_injectOrShowError("cranium.dll");
|
await _injectOrShowError("cranium.dll");
|
||||||
|
|
||||||
|
if(hosting){
|
||||||
|
_showServerLaunchingWarning();
|
||||||
|
}
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
_updateServerState(false);
|
_closeDialogIfOpen();
|
||||||
_onError(exception);
|
_onError(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onGameOutput(line) {
|
void _onEnd() {
|
||||||
|
_closeDialogIfOpen();
|
||||||
|
_onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _closeDialogIfOpen() {
|
||||||
|
if(!mounted){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var route = ModalRoute.of(context);
|
||||||
|
if(route != null && !route.isCurrent){
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showServerLaunchingWarning() async {
|
||||||
|
var result = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => ContentDialog(
|
||||||
|
content: const InfoLabel(
|
||||||
|
label: "Launching reboot server...",
|
||||||
|
child: SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: ProgressBar()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: FilledButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
_onStop();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: ButtonState.all(Colors.red)),
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(result != null && result){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onGameOutput(String line) {
|
||||||
if (line.contains("FOnlineSubsystemGoogleCommon::Shutdown()")) {
|
if (line.contains("FOnlineSubsystemGoogleCommon::Shutdown()")) {
|
||||||
_onStop();
|
_onStop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.contains("[UFortUIManagerWidget_NUI::SetUIState]") && line.contains("FrontEnd")) {
|
if (line.contains("Game Engine Initialized") && !_gameController.host.value) {
|
||||||
_injectOrShowError(_gameController.host.value ? "reboot.dll" : "console.dll");
|
_injectOrShowError("console.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.contains("added to UI Party led ") && _gameController.host.value){
|
||||||
|
_injectOrShowError("reboot.dll")
|
||||||
|
.then((value) => Navigator.of(context).pop(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Object?> _onError(exception) {
|
Future<Object?> _onError(Object exception) {
|
||||||
return showDialog(
|
return showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => ContentDialog(
|
builder: (context) => ContentDialog(
|
||||||
@@ -127,7 +193,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: ButtonState.all(Colors.red)),
|
backgroundColor: ButtonState.all(Colors.red)),
|
||||||
child: const Text('Close'),
|
child: const Text('Close'),
|
||||||
@@ -141,7 +207,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
_gameController.kill();
|
_gameController.kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _injectOrShowError(String binary) async {
|
Future<void> _injectOrShowError(String binary) async {
|
||||||
var gameProcess = _gameController.gameProcess;
|
var gameProcess = _gameController.gameProcess;
|
||||||
if (gameProcess == null) {
|
if (gameProcess == null) {
|
||||||
return;
|
return;
|
||||||
@@ -166,7 +232,7 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<String> _createProcessArguments() {
|
List<String> _createProcessArguments() {
|
||||||
return [
|
var args = [
|
||||||
"-epicapp=Fortnite",
|
"-epicapp=Fortnite",
|
||||||
"-epicenv=Prod",
|
"-epicenv=Prod",
|
||||||
"-epiclocale=en-us",
|
"-epiclocale=en-us",
|
||||||
@@ -179,5 +245,11 @@ class _LaunchButtonState extends State<LaunchButton> {
|
|||||||
"-AUTH_PASSWORD=Rebooted",
|
"-AUTH_PASSWORD=Rebooted",
|
||||||
"-AUTH_TYPE=epic"
|
"-AUTH_TYPE=epic"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if(_gameController.host.value){
|
||||||
|
args.addAll(["-log", "-nullrhi", "-nosplash", "-nosound", "-unattended"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ class _SmartSwitchState extends State<SmartSwitch> {
|
|||||||
|
|
||||||
double get _uncheckedOpacity => widget.enabled ? 0.8 : 0.5;
|
double get _uncheckedOpacity => widget.enabled ? 0.8 : 0.5;
|
||||||
|
|
||||||
void _onChanged(checked) {
|
void _onChanged(bool checked) {
|
||||||
if (!widget.enabled) {
|
if (!widget.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() => widget.value(checked));
|
setState(() => widget.value.value = checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:reboot_launcher/src/model/fortnite_version.dart';
|
|||||||
|
|
||||||
import 'package:reboot_launcher/src/controller/game_controller.dart';
|
import 'package:reboot_launcher/src/controller/game_controller.dart';
|
||||||
import 'package:reboot_launcher/src/widget/scan_local_version.dart';
|
import 'package:reboot_launcher/src/widget/scan_local_version.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../controller/build_controller.dart';
|
import '../controller/build_controller.dart';
|
||||||
|
|
||||||
@@ -142,7 +143,7 @@ class VersionSelector extends StatelessWidget {
|
|||||||
switch (result) {
|
switch (result) {
|
||||||
case 0:
|
case 0:
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Process.run("explorer.exe", [version.location.path]);
|
launchUrl(version.location.uri);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
73
lib/test.dart
Normal file
73
lib/test.dart
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:hex/hex.dart';
|
||||||
|
|
||||||
|
const String _original = "2d0069006e007600690074006500730065007300730069006f006e0020002d0069006e007600690074006500660072006f006d0020002d00700061007200740079005f006a006f0069006e0069006e0066006f005f0074006f006b0065006e0020002d007200650070006c0061007900";
|
||||||
|
const String _patched = "2d006c006f00670020002d006e006f00730070006c0061007300680020002d006e006f0073006f0075006e00640020002d006e0075006c006c0072006800690020002d007500730065006f006c0064006900740065006d00630061007200640073002000200020002000200020002000";
|
||||||
|
final Uint8List _originalBinary = Uint8List.fromList([
|
||||||
|
45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 115, 0, 101, 0, 115, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0, 45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 102, 0, 114, 0, 111, 0, 109, 0, 32, 0, 45, 0, 112, 0, 97, 0, 114, 0, 116, 0, 121, 0, 95, 0, 106, 0, 111, 0, 105, 0, 110, 0, 105, 0, 110, 0, 102, 0, 111, 0, 95, 0, 116, 0, 111, 0, 107, 0, 101, 0, 110, 0, 32, 0, 45, 0, 114, 0, 101, 0, 112, 0, 108, 0, 97, 0, 121, 0
|
||||||
|
]);
|
||||||
|
|
||||||
|
final Uint8List _patchedBinary = Uint8List.fromList([
|
||||||
|
45, 0, 108, 0, 111, 0, 103, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 112, 0, 108, 0, 97, 0, 115, 0, 104, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 111, 0, 117, 0, 110, 0, 100, 0, 32, 0, 45, 0, 110, 0, 117, 0, 108, 0, 108, 0, 114, 0, 104, 0, 105, 0, 32, 0, 45, 0, 117, 0, 115, 0, 101, 0, 111, 0, 108, 0, 100, 0, 105, 0, 116, 0, 101, 0, 109, 0, 99, 0, 97, 0, 114, 0, 100, 0, 115, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0
|
||||||
|
]);
|
||||||
|
|
||||||
|
Future<String> patchExeHex(File file) async {
|
||||||
|
Future<String> replaceBinary(File file, String original, String replacement) async {
|
||||||
|
var read = await file.readAsBytes();
|
||||||
|
var hex = HEX.encode(read);
|
||||||
|
var fixed = hex.replaceAll(original, replacement);
|
||||||
|
return fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await replaceBinary(file, _original, _patched);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> patchExeBinary(File file) async {
|
||||||
|
Future<String> replaceBinary(File file, Uint8List original, Uint8List replacement) async {
|
||||||
|
if(original.length != replacement.length){
|
||||||
|
throw Exception("Cannot mutate length of binary file");
|
||||||
|
}
|
||||||
|
|
||||||
|
var read = await file.readAsBytes();
|
||||||
|
var length = await file.length();
|
||||||
|
var offset = 0;
|
||||||
|
var counter = 0;
|
||||||
|
while(offset < length){
|
||||||
|
if(read[offset] == original[counter]){
|
||||||
|
counter++;
|
||||||
|
}else {
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
if(counter == original.length){
|
||||||
|
for(var index = 0; index < replacement.length; index++){
|
||||||
|
read[offset - counter + index] = replacement[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return HEX.encode(read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exception("No match");
|
||||||
|
}
|
||||||
|
|
||||||
|
return await replaceBinary(file, _originalBinary, _patchedBinary);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
var file = File("D:\\Fortnite73\\FortniteGame\\Binaries\\Win64\\FortniteClient-Win64-Shipping.exe");
|
||||||
|
var hexed = await patchExeHex(file);
|
||||||
|
var binary = await patchExeBinary(file);
|
||||||
|
var offset = 0;
|
||||||
|
while(offset < hexed.length){
|
||||||
|
if(hexed[offset] != binary[offset]){
|
||||||
|
print("Difference ${hexed[offset]} != ${binary[offset]} at $offset");
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
print(hexed == binary);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: reboot_launcher
|
name: reboot_launcher
|
||||||
description: Launcher for project reboot
|
description: Launcher for project reboot
|
||||||
version: "3.6.0"
|
version: "3.7.0"
|
||||||
|
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ dependencies:
|
|||||||
get: ^4.6.5
|
get: ^4.6.5
|
||||||
get_storage: ^2.0.3
|
get_storage: ^2.0.3
|
||||||
window_manager: ^0.2.7
|
window_manager: ^0.2.7
|
||||||
|
hex: ^0.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -48,7 +49,7 @@ msix_config:
|
|||||||
display_name: Reboot Launcher
|
display_name: Reboot Launcher
|
||||||
publisher_display_name: Auties00
|
publisher_display_name: Auties00
|
||||||
identity_name: 31868Auties00.RebootLauncher
|
identity_name: 31868Auties00.RebootLauncher
|
||||||
msix_version: 3.6.0.0
|
msix_version: 3.7.0.0
|
||||||
publisher: CN=E6CD08C6-DECF-4034-A3EB-2D5FA2CA8029
|
publisher: CN=E6CD08C6-DECF-4034-A3EB-2D5FA2CA8029
|
||||||
logo_path: ./assets/icons/reboot.ico
|
logo_path: ./assets/icons/reboot.ico
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|||||||
Reference in New Issue
Block a user