mirror of
https://github.com/felixrieseberg/macintosh.js.git
synced 2024-06-12 02:29:29 +00:00
Compare commits
12 Commits
d58444bc18
...
7dda450bf6
Author | SHA1 | Date | |
---|---|---|---|
|
7dda450bf6 | ||
|
d68097b59b | ||
|
34eccc706c | ||
|
cc94f198e2 | ||
|
f5ef5da750 | ||
|
1482f6d443 | ||
|
1533ba7ec0 | ||
|
8a8aa0e7eb | ||
|
05136c28c1 | ||
|
e5b24cc04a | ||
|
8821a4749f | ||
|
4d57fc494c |
33
.github/workflows/build.yml
vendored
33
.github/workflows/build.yml
vendored
|
@ -12,15 +12,15 @@ jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 15.x
|
node-version: lts/*
|
||||||
- name: Get yarn cache directory path
|
- name: Get yarn cache directory path
|
||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
- uses: actions/cache@v1
|
- uses: actions/cache@v3
|
||||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
|
@ -37,17 +37,32 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
# Build for supported platforms
|
||||||
|
# https://github.com/electron/electron-packager/blob/ebcbd439ff3e0f6f92fa880ff28a8670a9bcf2ab/src/targets.js#L9
|
||||||
|
# 32-bit Linux unsupported as of 2019: https://www.electronjs.org/blog/linux-32bit-support
|
||||||
os: [ macOS-latest, ubuntu-latest, windows-latest ]
|
os: [ macOS-latest, ubuntu-latest, windows-latest ]
|
||||||
|
arch: [ x64, arm64 ]
|
||||||
|
include:
|
||||||
|
- os: windows-latest
|
||||||
|
arch: ia32
|
||||||
|
- os: ubuntu-latest
|
||||||
|
arch: armv7l
|
||||||
|
# Publishing artifacts for multiple Windows architectures has
|
||||||
|
# a bug which can cause the wrong architecture to be downloaded
|
||||||
|
# for an update, so until that is fixed, only build Windows x64
|
||||||
|
exclude:
|
||||||
|
- os: windows-latest
|
||||||
|
arch: arm64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 12.x
|
node-version: lts/*
|
||||||
- name: Get yarn cache directory path
|
- name: Get yarn cache directory path
|
||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
- uses: actions/cache@v1
|
- uses: actions/cache@v3
|
||||||
if: matrix.os != 'macOS-latest'
|
if: matrix.os != 'macOS-latest'
|
||||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||||
with:
|
with:
|
||||||
|
@ -83,7 +98,7 @@ jobs:
|
||||||
run: yarn
|
run: yarn
|
||||||
- name: Make
|
- name: Make
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
run: yarn make --arch=all
|
run: yarn make --arch=${{ matrix.arch }}
|
||||||
env:
|
env:
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
|
|
16
package.json
16
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "macintosh.js",
|
"name": "macintosh.js",
|
||||||
"productName": "macintosh.js",
|
"productName": "macintosh.js",
|
||||||
"version": "1.1.0",
|
"version": "1.2.3",
|
||||||
"description": "Macintosh's System 8 in an Electron app. I'm sorry.",
|
"description": "Macintosh's System 8 in an Electron app. I'm sorry.",
|
||||||
"main": "src/main/index.js",
|
"main": "src/main/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
"make": "electron-forge make",
|
"make": "electron-forge make",
|
||||||
"publish": "electron-forge publish",
|
"publish": "electron-forge publish",
|
||||||
"lint": "npx prettier --check src/{main,renderer}/*.{js,css} && npm run check-links",
|
"lint": "npx prettier --check src/{main,renderer}/*.{js,css} && npm run check-links",
|
||||||
"fix": "npx prettier --write src/{main,renderer}/*.{js,css}",
|
"fix": "npx prettier --write \"src/{main,renderer}/**.{js,css}\"",
|
||||||
"check-links": "node tools/check-links.js"
|
"check-links": "node tools/check-links.js"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
@ -27,12 +27,12 @@
|
||||||
"update-electron-app": "^2.0.1"
|
"update-electron-app": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-forge/cli": "6.0.0-beta.54",
|
"@electron-forge/cli": "6.0.5",
|
||||||
"@electron-forge/maker-deb": "6.0.0-beta.54",
|
"@electron-forge/maker-deb": "6.0.5",
|
||||||
"@electron-forge/maker-rpm": "6.0.0-beta.54",
|
"@electron-forge/maker-rpm": "6.0.5",
|
||||||
"@electron-forge/maker-squirrel": "6.0.0-beta.54",
|
"@electron-forge/maker-squirrel": "6.0.5",
|
||||||
"@electron-forge/maker-zip": "6.0.0-beta.54",
|
"@electron-forge/maker-zip": "6.0.5",
|
||||||
"electron": "11.1.1",
|
"electron": "23.1.3",
|
||||||
"node-fetch": "^2.6.1"
|
"node-fetch": "^2.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const { app, dialog } = require("electron");
|
const { app, dialog } = require("electron");
|
||||||
|
const { getIsDevMode } = require("./devmode");
|
||||||
|
|
||||||
// If the app doesn't run from the /Applications folder,
|
// If the app doesn't run from the /Applications folder,
|
||||||
// we don't get to create files, which keeps the emulator from
|
// we don't get to create files, which keeps the emulator from
|
||||||
|
@ -8,6 +9,10 @@ function moveToAppFolderMaybe() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getIsDevMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (app.isInApplicationsFolder()) {
|
if (app.isInApplicationsFolder()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { app, BrowserWindow, shell } = require("electron");
|
const { BrowserWindow, shell } = require("electron");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const { getIsDevMode } = require("./devmode");
|
const { getIsDevMode } = require("./devmode");
|
||||||
|
@ -61,18 +61,31 @@ function createWindow() {
|
||||||
width: 900,
|
width: 900,
|
||||||
height: 730,
|
height: 730,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
frame: false,
|
frame: true,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
resizable: false,
|
resizable: true,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
|
nodeIntegrationInWorker: true,
|
||||||
nativeWindowOpen: true,
|
nativeWindowOpen: true,
|
||||||
|
contextIsolation: false,
|
||||||
navigateOnDragDrop: false,
|
navigateOnDragDrop: false,
|
||||||
nodeIntegrationInWorker: true,
|
nodeIntegrationInWorker: true,
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Ensure that we have access to SharedArrayBuffer
|
||||||
|
mainWindow.webContents.session.webRequest.onHeadersReceived(
|
||||||
|
(details, callback) => {
|
||||||
|
details.responseHeaders["Cross-Origin-Opener-Policy"] = ["same-origin"];
|
||||||
|
details.responseHeaders["Cross-Origin-Embedder-Policy"] = [
|
||||||
|
"require-corp",
|
||||||
|
];
|
||||||
|
callback({ responseHeaders: details.responseHeaders });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// and load the index.html of the app.
|
// and load the index.html of the app.
|
||||||
mainWindow.loadFile(path.join(__dirname, "../renderer/index.html"));
|
mainWindow.loadFile(path.join(__dirname, "../renderer/index.html"));
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,63 @@
|
||||||
const { videoModeBufferView } = require("./video");
|
const { videoModeBufferView } = require("./video");
|
||||||
const { audioContext } = require("./audio");
|
const BITS = 4;
|
||||||
|
const SCREEN_BUFFER_SIZE = 800 * 600 * BITS; // 32bpp;
|
||||||
const SCREEN_WIDTH = 800;
|
|
||||||
const SCREEN_HEIGHT = 600;
|
|
||||||
const SCREEN_BUFFER_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT * 4; // 32bpp;
|
|
||||||
|
|
||||||
const screenBuffer = new SharedArrayBuffer(SCREEN_BUFFER_SIZE);
|
const screenBuffer = new SharedArrayBuffer(SCREEN_BUFFER_SIZE);
|
||||||
const screenBufferView = new Uint8Array(screenBuffer);
|
const screenBufferView = new Uint8Array(screenBuffer);
|
||||||
|
|
||||||
canvas.width = SCREEN_WIDTH;
|
let screenWidth = 800;
|
||||||
canvas.height = SCREEN_HEIGHT;
|
let screenHeight = 600;
|
||||||
|
|
||||||
|
canvas.width = screenWidth;
|
||||||
|
canvas.height = screenHeight;
|
||||||
|
|
||||||
const canvasCtx = canvas.getContext("2d");
|
const canvasCtx = canvas.getContext("2d");
|
||||||
const imageData = canvasCtx.createImageData(SCREEN_WIDTH, SCREEN_HEIGHT);
|
let imageData = canvasCtx.createImageData(screenWidth, screenHeight);
|
||||||
|
|
||||||
|
window.addEventListener("resize", () => {
|
||||||
|
screenHeight = window.innerHeight - 35;
|
||||||
|
screenWidth = Math.floor(screenHeight * (4 / 3));
|
||||||
|
if (window.innerWidth < screenWidth) {
|
||||||
|
screenWidth = window.innerWidth;
|
||||||
|
screenHeight = Math.floor(screenWidth * 0.75);
|
||||||
|
}
|
||||||
|
canvas.width = screenWidth;
|
||||||
|
canvas.height = screenHeight;
|
||||||
|
imageData = canvasCtx.createImageData(screenWidth, screenHeight);
|
||||||
|
});
|
||||||
|
|
||||||
let stopDrawing = false;
|
let stopDrawing = false;
|
||||||
|
|
||||||
function drawScreen() {
|
function drawScreen() {
|
||||||
if (stopDrawing) return;
|
if (stopDrawing) return;
|
||||||
const pixelsRGBA = imageData.data;
|
const pixelsRGBA = imageData.data;
|
||||||
const numPixels = SCREEN_WIDTH * SCREEN_HEIGHT;
|
const numPixels = screenWidth * screenHeight;
|
||||||
const expandedFromPalettedMode = videoModeBufferView[3];
|
const expandedFromPalettedMode = videoModeBufferView[3];
|
||||||
const start = audioContext.currentTime;
|
|
||||||
|
|
||||||
if (expandedFromPalettedMode) {
|
if (expandedFromPalettedMode) {
|
||||||
for (var i = 0; i < numPixels; i++) {
|
for (let i = 0; i < numPixels; i++) {
|
||||||
// palette
|
// palette
|
||||||
pixelsRGBA[i * 4 + 0] = screenBufferView[i * 4 + 0];
|
pixelsRGBA[i * BITS + 0] = screenBufferView[i * BITS + 0];
|
||||||
pixelsRGBA[i * 4 + 1] = screenBufferView[i * 4 + 1];
|
pixelsRGBA[i * BITS + 1] = screenBufferView[i * BITS + 1];
|
||||||
pixelsRGBA[i * 4 + 2] = screenBufferView[i * 4 + 2];
|
pixelsRGBA[i * BITS + 2] = screenBufferView[i * BITS + 2];
|
||||||
pixelsRGBA[i * 4 + 3] = 255; // full opacity
|
pixelsRGBA[i * BITS + 3] = 255; // full opacity
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var i = 0; i < numPixels; i++) {
|
for (let i = 0; i < screenHeight; i++) {
|
||||||
// ARGB
|
for (let j = 0; j < screenWidth; j++) {
|
||||||
pixelsRGBA[i * 4 + 0] = screenBufferView[i * 4 + 1];
|
// ARGB
|
||||||
pixelsRGBA[i * 4 + 1] = screenBufferView[i * 4 + 2];
|
const xRatio = 800 / screenWidth;
|
||||||
pixelsRGBA[i * 4 + 2] = screenBufferView[i * 4 + 3];
|
const yRatio = 600 / screenHeight;
|
||||||
pixelsRGBA[i * 4 + 3] = 255; // full opacity
|
const px = Math.floor(j * xRatio);
|
||||||
|
const py = Math.floor(i * yRatio);
|
||||||
|
pixelsRGBA[(i * screenWidth + j) * 4 + 0] =
|
||||||
|
screenBufferView[(py * 800 + px) * 4 + 1]; //- lineMult];
|
||||||
|
pixelsRGBA[(i * screenWidth + j) * 4 + 1] =
|
||||||
|
screenBufferView[(py * 800 + px) * 4 + 2]; //- lineMult];
|
||||||
|
pixelsRGBA[(i * screenWidth + j) * 4 + 2] =
|
||||||
|
screenBufferView[(py * 800 + px) * 4 + 3]; //- lineMult];
|
||||||
|
pixelsRGBA[(i * screenWidth + j) * 4 + 3] = 255; // full opacity
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +89,7 @@ module.exports = {
|
||||||
screenBufferView,
|
screenBufferView,
|
||||||
SCREEN_BUFFER_SIZE,
|
SCREEN_BUFFER_SIZE,
|
||||||
drawScreen,
|
drawScreen,
|
||||||
SCREEN_WIDTH,
|
SCREEN_WIDTH: screenWidth,
|
||||||
SCREEN_HEIGHT,
|
SCREEN_HEIGHT: screenHeight,
|
||||||
setCanvasBlank,
|
setCanvasBlank,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user