Monty10

Active Member
Jan 30, 2024
894
1,007
179
You have to understand: the dev doesn’t include malware in his game, but the people who share his game on this forum might. I’m not saying that they do necessarily or even frequently, but they might.

Normally, some forum moderators will check the game before updating the OP; last time, some malware escaped their attention, that’s all.
You still didn't answer me
is this update has virus or not?
 

JYWH23

Newbie
Jan 19, 2022
32
47
86
I know this has been asked a thousand times before but hope is never lost, anyone could share their savefile, I messed with mine like an idiot and I don't want to click through the whole game again.
 

Groomtinger

Newbie
Aug 9, 2017
78
273
200
Unlock All Collector Cards
This is only visual, and doesn't change any actual data

Modify /resources/app/data//SCRIPTS.js

Find @ L37886
JavaScript:
"formulas": [
    $(function() {
        if ($dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked) {
            o.image = o.parent.data[0].thumb.name;
            return o.imageFolder = o.parent.data[0].thumb.folderPath;
        }
    }), $(function() {
        if (!$dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked) {
            return o.image = "UI/locked.png";
        }
    })
]
Replace with:

JavaScript:
"formulas": [
    $(function() {
        if (true) {//$dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked
            o.image = o.parent.data[0].thumb.name;
            return o.imageFolder = o.parent.data[0].thumb.folderPath;
        }
    }), $(function() {
        if (false) {//!$dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked
            return o.image = "UI/locked.png";
        }
    })
]
I'm trying to figure out how to do the scenes themselves, so we don't always need a full save, but either I'm done or that's somewhere deeper I haven't found yet. Will update when I find it.
 
  • Like
Reactions: himler

himler

Member
Jun 16, 2017
124
116
246
Unlock All Collector Cards
This is only visual, and doesn't change any actual data

Modify /resources/app/data//SCRIPTS.js

Find @ L37886
JavaScript:
"formulas": [
    $(function() {
        if ($dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked) {
            o.image = o.parent.data[0].thumb.name;
            return o.imageFolder = o.parent.data[0].thumb.folderPath;
        }
    }), $(function() {
        if (!$dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked) {
            return o.image = "UI/locked.png";
        }
    })
]
Replace with:

JavaScript:
"formulas": [
    $(function() {
        if (true) {//$dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked
            o.image = o.parent.data[0].thumb.name;
            return o.imageFolder = o.parent.data[0].thumb.folderPath;
        }
    }), $(function() {
        if (false) {//!$dataFields.globalData.cgGallery[o.parent.data[0].index].unlocked
            return o.image = "UI/locked.png";
        }
    })
]
I'm trying to figure out how to do the scenes themselves, so we don't always need a full save, but either I'm done or that's somewhere deeper I haven't found yet. Will update when I find it.
I found this on line 28490
Code:
/**
  * @method commandUnlockCG
  * @protected
   */

and changed the entire loop with this:
JavaScript:
Component_CommandInterpreter.prototype.commandUnlockCG = function() {
  for (var key in RecordManager.cgGallery) {
    var cg = RecordManager.cgGallery[key];
    GameManager.globalData.cgGallery[cg.index] = { unlocked: true };
  }
  return GameManager.saveGlobalData();
};
Not sure if it works tho since I had a bunch of the gallery unlocked and don't know what scenes were missing.
 
  • Like
Reactions: jhose15xs

Groomtinger

Newbie
Aug 9, 2017
78
273
200
Not sure if it works tho since I had a bunch of the gallery unlocked and don't know what scenes were missing.
Nah, the cgGallery is referring to the collector cards. Nothing in any of the human-readable files relate to the Scene Gallery, that I could find. Before I gave up, I was looking into the structure of the game variables from the dev console. I could find their definitions, but not where they're set. I'm not super smart, tho.

If you want to enable the dev console yourself to take a look around:

Edit main.js, after:

win.loadFile('index.html')

Put:

win.webContents.openDevTools({ mode: 'detach' });

EDIT:

I just figured out how to decode the json.js files in the resource folders.

Seeing if this is anything useful RQ.

EDIT2:

The same logic to decrypt the json.js files can be successfully applied to all the images and whatnot.

EDIT3:

I. Fucking. Did. It.

himler

Drop and replace this file in /resources/app/data



I'll paste the code I used to make this happen, if you don't want to use my shady URL (I couldn't upload here because it has an unallowed file extension, and I didn't feel like bypassing that was within the spirit of the rules).

DECODE ALL FILES
JavaScript:
const fs = require('fs');
const path = require('path');

const key = [42, 11, 22, 79, 43, 37, 14, 11, 24, 30];
const extractedDir = path.join(__dirname, 'extracted');

if (!fs.existsSync(extractedDir)) {
  fs.mkdirSync(extractedDir);
}

const files = fs.readdirSync(__dirname);
const encryptedFiles = files.filter(f => f.endsWith('.json.js'));

encryptedFiles.forEach(file => {
  const encryptedData = fs.readFileSync(path.join(__dirname, file));
  const decrypted = Buffer.alloc(encryptedData.length);

  for (let i = 0; i < encryptedData.length; i++) {
    decrypted[i] = encryptedData[i] ^ key[i % key.length];
  }

  const outputFileName = file.replace(/\.js$/, '');
  const outputPath = path.join(extractedDir, outputFileName);
  fs.writeFileSync(outputPath, decrypted);

  const content = decrypted.toString('utf8').toLowerCase();
  if (content.includes('scene gallery')) {
    console.log(`Found "gallery" in: ${outputFileName}`);
  }
});
Find the correct file: CD16B1B8867710487F3B6B911CF0477E444F.json

Temporarily remove GS.dataCache['CD16B1B8867710487F3B6B911CF0477E444F'] = at the BEGINNING, beause otherwise it's invalid JSON and we won't be able to parse it.

MODIFY THE GALLERY CONDITION CHECKS
(Basically, this just changes the conditions to be <= 99999)
JavaScript:
const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'CD16B1B8867710487F3B6B911CF0477E444F.json');

let json;
try {
  const content = fs.readFileSync(filePath, 'utf-8');
  json = JSON.parse(content);
} catch (e) {
  console.error('Failed to read or parse file:', e.message);
  process.exit(1);
}

function modifyConditions(obj) {
  if (Array.isArray(obj)) {
    obj.forEach(modifyConditions);
  } else if (typeof obj === 'object' && obj !== null) {
    if (obj.id === 'gs.Condition' && obj.params) {
      obj.params.operation = 5;
      obj.params.numberValue = 99999;
    }
    Object.values(obj).forEach(modifyConditions);
  }
}

modifyConditions(json);

fs.writeFileSync(filePath, JSON.stringify(json, null, 2), 'utf-8');
console.log('All gs.Condition blocks set to always-true.');
Put GS.dataCache['CD16B1B8867710487F3B6B911CF0477E444F'] = back at the beginning of the file.

RE-ENCRYPT THE FILE:
JavaScript:
const fs = require('fs');

const key = [42, 11, 22, 79, 43, 37, 14, 11, 24, 30];

const fileName = 'CD16B1B8867710487F3B6B911CF0477E444F.json';

const data = fs.readFileSync(fileName);
const encrypted = Buffer.alloc(data.length);

for (let i = 0; i < data.length; i++) {
  encrypted[i] = data[i] ^ key[i % key.length];
}

fs.writeFileSync(fileName + '.js', encrypted);
console.log(`Re-encrypted: ${fileName} → ${fileName}.js`);
Then just toss it back in.

EDIT FINAL:

It is worth noting that, while every new scene will likely invalidate this fix, the METHOD to achieve it will NEVER change (although, the encryption keys COULD be changed, though those are easy to find).
 
Last edited:

Over99lord

Newbie
May 28, 2019
18
1
92
Nah, the cgGallery is referring to the collector cards. Nothing in any of the human-readable files relate to the Scene Gallery, that I could find. Before I gave up, I was looking into the structure of the game variables from the dev console. I could find their definitions, but not where they're set. I'm not super smart, tho.

If you want to enable the dev console yourself to take a look around:

Edit main.js, after:

win.loadFile('index.html')

Put:

win.webContents.openDevTools({ mode: 'detach' });

EDIT:

I just figured out how to decode the json.js files in the resource folders.

Seeing if this is anything useful RQ.

EDIT2:

The same logic to decrypt the json.js files can be successfully applied to all the images and whatnot.

EDIT3:

I. Fucking. Did. It.

himler

Drop and replace this file in /resources/app/data

Mega

I'll paste the code I used to make this happen, if you don't want to use my shady URL (I couldn't upload here because it has an unallowed file extension, and I didn't feel like bypassing that was within the spirit of the rules).

DECODE ALL FILES
JavaScript:
const fs = require('fs');
const path = require('path');

const key = [42, 11, 22, 79, 43, 37, 14, 11, 24, 30];
const extractedDir = path.join(__dirname, 'extracted');

if (!fs.existsSync(extractedDir)) {
  fs.mkdirSync(extractedDir);
}

const files = fs.readdirSync(__dirname);
const encryptedFiles = files.filter(f => f.endsWith('.json.js'));

encryptedFiles.forEach(file => {
  const encryptedData = fs.readFileSync(path.join(__dirname, file));
  const decrypted = Buffer.alloc(encryptedData.length);

  for (let i = 0; i < encryptedData.length; i++) {
    decrypted[i] = encryptedData[i] ^ key[i % key.length];
  }

  const outputFileName = file.replace(/\.js$/, '');
  const outputPath = path.join(extractedDir, outputFileName);
  fs.writeFileSync(outputPath, decrypted);

  const content = decrypted.toString('utf8').toLowerCase();
  if (content.includes('scene gallery')) {
    console.log(`Found "gallery" in: ${outputFileName}`);
  }
});
Find the correct file: CD16B1B8867710487F3B6B911CF0477E444F.json

Temporarily remove GS.dataCache['CD16B1B8867710487F3B6B911CF0477E444F'] = at the BEGINNING, beause otherwise it's invalid JSON and we won't be able to parse it.

MODIFY THE GALLERY CONDITION CHECKS
(Basically, this just changes the conditions to be <= 99999)
JavaScript:
const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'CD16B1B8867710487F3B6B911CF0477E444F.json');

let json;
try {
  const content = fs.readFileSync(filePath, 'utf-8');
  json = JSON.parse(content);
} catch (e) {
  console.error('Failed to read or parse file:', e.message);
  process.exit(1);
}

function modifyConditions(obj) {
  if (Array.isArray(obj)) {
    obj.forEach(modifyConditions);
  } else if (typeof obj === 'object' && obj !== null) {
    if (obj.id === 'gs.Condition' && obj.params) {
      obj.params.operation = 5;
      obj.params.numberValue = 99999;
    }
    Object.values(obj).forEach(modifyConditions);
  }
}

modifyConditions(json);

fs.writeFileSync(filePath, JSON.stringify(json, null, 2), 'utf-8');
console.log('All gs.Condition blocks set to always-true.');
Put GS.dataCache['CD16B1B8867710487F3B6B911CF0477E444F'] = back at the beginning of the file.

RE-ENCRYPT THE FILE:
JavaScript:
const fs = require('fs');

const key = [42, 11, 22, 79, 43, 37, 14, 11, 24, 30];

const fileName = 'CD16B1B8867710487F3B6B911CF0477E444F.json';

const data = fs.readFileSync(fileName);
const encrypted = Buffer.alloc(data.length);

for (let i = 0; i < data.length; i++) {
  encrypted[i] = data[i] ^ key[i % key.length];
}

fs.writeFileSync(fileName + '.js', encrypted);
console.log(`Re-encrypted: ${fileName} → ${fileName}.js`);
Then just toss it back in.

EDIT FINAL:

It is worth noting that, while every new scene will likely invalidate this fix, the METHOD to achieve it will NEVER change (although, the encryption keys COULD be changed, though those are easy to find).
Any chance you can whip something up to un-encrypt the pictures in resources\app\resources\Graphics?
 

Groomtinger

Newbie
Aug 9, 2017
78
273
200
Any chance you can whip something up to un-encrypt the pictures in resources\app\resources\Graphics?
Sure, I ran a pass through the folders, renaming the top level to keep everything separated and easy to zip up and upload.

JavaScript:
const fs = require('fs');
const path = require('path');
const key = [42, 11, 22, 79, 43, 37, 14, 11, 24, 30];
const scriptName = path.basename(__filename);

function isLikelyEncrypted(buffer) {
  const sample = buffer.slice(0, 50);
  let nonPrintable = 0;

  for (const byte of sample) {
    if (byte < 9 || (byte > 13 && byte < 32) || byte > 126) {
      nonPrintable++;
    }
  }

  return nonPrintable > sample.length * 0.3;
}

function decryptBuffer(buffer, key) {
  const decrypted = Buffer.alloc(buffer.length);
  for (let i = 0; i < buffer.length; i++) {
    decrypted[i] = buffer[i] ^ key[i % key.length];
  }
  return decrypted;
}

function walkDir(dir, callback) {
  fs.readdirSync(dir).forEach(file => {
    const fullPath = path.join(dir, file);
    const stat = fs.statSync(fullPath);
    if (stat.isDirectory()) {
      walkDir(fullPath, callback);
    } else {
      callback(fullPath);
    }
  });
}

function getDecryptedPath(filePath, rootDir) {
  const relativePath = path.relative(rootDir, filePath);
  const parts = relativePath.split(path.sep);
  const topLevel = parts[0];
  const newTop = `${topLevel}_Decrypted`;
  return path.join(rootDir, newTop, ...parts.slice(1));
}

const rootDir = __dirname;

walkDir(rootDir, (filePath) => {
  const filename = path.basename(filePath);

  if (filename === scriptName) {
    console.log(`Skipped script file: ${filePath}`);
    return;
  }

  const rawData = fs.readFileSync(filePath);
  const looksEncrypted = isLikelyEncrypted(rawData);

  if (looksEncrypted) {
    const decryptedData = decryptBuffer(rawData, key);
    const outputPath = getDecryptedPath(filePath, rootDir);

    fs.mkdirSync(path.dirname(outputPath), { recursive: true });
    fs.writeFileSync(outputPath, decryptedData);

    console.log(`Decrypted: ${filePath} → ${outputPath}`);
  } else {
    console.log(`Probably not encrypted: ${filePath}`);
  }
});
Here's the rip:


EDIT: Skipped webm files (but still copied them), deleted fonts folder. Without going through every file, this should be perfectly viewable.
 
Last edited:

KaiCade1

New Member
Dec 14, 2024
4
4
71
Hey guys can anyone confirm if there is any malware on this 0.76 update? Im 99% sure there isnt but just im new to this stuff so would like confirmation.
 

RackUser

Newbie
Aug 21, 2023
47
34
102
Hey guys can anyone confirm if there is any malware on this 0.76 update? Im 99% sure there isnt but just im new to this stuff so would like confirmation.
its been two months since upload so probably not, and if your a newbie as a rule of thumb never download day one leaks if you have sensitive information on your computer or don't have a sandbox set up.
 
  • Like
Reactions: KaiCade1
Jan 26, 2025
23
6
3
i can't believe there are so many people who will risk getting malware in their computer just to play the game? like there are many others, why be dumb about it? some people even say "There is no malware in the new release i think" like what are you, stupid? As a cybersecurity specialist, i'm very much disappointed in naiveness of you people
 
4.10 star(s) 29 Votes