From bf1f043bc4adba67ce8cb8c6bdbd97f843ade86b Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Mon, 27 Jul 2020 10:33:55 -0700 Subject: [PATCH] fix: A whole bunch of cleaning up --- CREDITS.md | 15 +++++ README.md | 35 +++++++++++ assets/icon.icns | Bin 0 -> 36684 bytes assets/icon.ico | Bin 0 -> 4286 bytes assets/icon.png | Bin 0 -> 14748 bytes forge.config.js | 80 +++++++++++++++++++++++++ package.json | 29 +-------- src/basilisk/BasiliskII-worker-boot.js | 24 ++++++++ src/main/devmode.js | 21 ++++--- src/main/index.js | 55 ++++++++++------- src/main/ipc.js | 19 +++++- src/main/squirrel.js | 7 +++ src/main/update.js | 14 +++++ src/main/windows.js | 5 ++ src/renderer/audio.js | 17 ------ src/renderer/controls.js | 7 ++- src/renderer/credits.html | 13 ++-- src/renderer/credits.js | 19 ++++++ src/renderer/help.html | 15 ++--- src/renderer/help.js | 46 ++++++++------ src/renderer/index.html | 2 +- src/renderer/ipc.js | 12 ++++ src/renderer/style/index.css | 15 +++++ src/renderer/worker.js | 4 +- tools/notarize.js | 30 ++++++++++ yarn.lock | 29 ++++++++- 26 files changed, 401 insertions(+), 112 deletions(-) create mode 100644 CREDITS.md create mode 100644 README.md create mode 100644 assets/icon.icns create mode 100644 assets/icon.ico create mode 100644 assets/icon.png create mode 100644 forge.config.js create mode 100644 src/main/squirrel.js create mode 100644 src/main/update.js create mode 100644 src/renderer/credits.js create mode 100644 tools/notarize.js diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 0000000..d2c4536 --- /dev/null +++ b/CREDITS.md @@ -0,0 +1,15 @@ +# macintosh.js Credits + +This app by Felix Rieseberg. The real work was done by the people below: + +**Emulator**: Basilisk II, a 68k Macintosh emulator, by [Christian Bauer et al](http://basilisk.cebix.net), modified and compiled [with Emscripten](https://jamesfriend.com.au/basilisk-ii-classic-mac-emulator-in-the-browser) by [James Friend](https://jamesfriend.com.au). + +**Installed software** from vintage computing archives: [WinWorldPC](https://winworldpc.com), [Macintosh Garden](https://macintoshgarden.org), and [Macintosh Repository](https://www.macintoshrepository.org/). + +This software is not affiliated with nor authorized by Apple. It is provided for educational purposes only. This is an unstable toy and should not be expected to work properly. + +# Licenses + +The [source code for this app can be found on GitHub](https://github.com/felixrieseberg/macintosh). + +Basilisk II and its components are released under the GNU GPL. See [LICENSE](src/basilisk/LICENSE.txt) for details. diff --git a/README.md b/README.md new file mode 100644 index 0000000..38b554e --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# macintosh.js + +This is Mac OS 8, running in an [Electron](https://electronjs.org/) app. Yes, it's the full thing. I'm sorry. + +## Downloads +| | Windows | macOS | Linux | +|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Standalone Download | 📦[Standalone, 32-bit](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-2.2.1-win32-standalone-ia32.zip)
📦[Standalone, 64-bit](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-2.2.1-win32-standalone-x64.zip) | 📦[Standalone](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-macos-2.2.1.zip) | | +| Installer | 💽[Setup, 64-bit](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-2.2.1-setup-win32-x64.exe)
💽[Setup, 32-bit](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-2.2.1-setup-win32-ia32.exe) | | 💽[deb, 64-bit](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-linux-2.2.1_amd64.deb)
💽[rpm, 64-bit](https://github.com/felixrieseberg/macintosh.js/releases/download/v2.2.1/macintosh.js-linux-2.2.1.x86_64.rpm) | + +![Screenshot]() + +## Does it work? +Yes! Quite well, actually - on macOS, Windows, and Linux. Bear in mind that this is written entirely in JavaScript, so please adjust your expectations. The virtual machine is emulating a Motorola CPU, which Apple used before switching to IBM's PowerPC architecture in the late 1990s. + +## Should this have been a native app? +Absolutely. + +## Does it run my favorite game or app? +You'll likely be better off with an actual virtualization app, but the short answer is yes. In fact, you'll find various games and demos preinstalled, thanks to an old MacWorld Demo CD from 1997. Namely, Oregon Trail, Duke Nukem 3D, Civilization II, Alley 19 Bowling, Damage Incorporated, and Dungeons & Dragons. + +There are also various apps and trials preinstalled, including Photoshop 3, Premiere 4, Illustrator 5.5, StuffIt Expander, the Apple Web Page Construction Kit, and more. + +## Can I transfer files from and to the machine? + +Yes, you can. Click on the "Help" button at the bottom of the running app to see instructions. + +## Can I connect to the Internet? + +No. For what it's worth, the web was quite different 30 years ago - and you wouldn't be able to open even Google. However, Internet Explorer and Netscape are installed, as is the "Web Sharing Server", if you want to play around a bit. + +## License + +This project is provided for educational purposes only. It is not affiliated with and has +not been approved by Apple. diff --git a/assets/icon.icns b/assets/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..6f016302b4493d07c47a601755688c603aa334a9 GIT binary patch literal 36684 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 MJKzNI823K@2Gn2|Pyhe` literal 0 HcmV?d00001 diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..06acacfd41dd51f696795078f7644b53e6250880 GIT binary patch literal 14748 zcmZv@2|U!__douck%TnbNU~LuWX+N^(H;pYWGDMBJA)a?QYs=#lzl1tn%$^K_I=Hk zvhQJxF=l@Er8l3)_y73!c$D1Ny=S}Up4U0gb6?L@lx{OI9A|(ah)Mp=4OIw2g8w3+ zeS5)=Rktn@_<}boZhg_Z1 z%%UeZyqW*B52*)Tn>lI?{+O z?W?3gd4te;v^~ajp(%4Zw#q9ltxRJ`rgNxssC91rV^n@db;QNVq1G#to>(id9&-11 zL3{M%*8Hk%9nZ56V)NNvb&aP46wfo}Yk^YJ<0Qw(l3^#4S;~oP`*@!9DMioT@0FF| zpdF3Vxve7|E&GBQj1xkq2Bt`uG^1r|wyVy)?D&D4Q(*m_8Y32hboR(4Y#C91i8Y&7 z>GpkYcznO{r&-yHk$PldqD-$%w$q0=c|bhmPD=IK;s-8$GPPvSl0O7QIFusq;5F*x zy-XDvW`>t0iU+)J)CTKbWqe)HzXz{sR7jt-M|_LJE{-U*u=eK%Ox>Z~Sek=tWchCs^`^#aR=V3@Fhus1`{b~v zcW>hbss_jB4PHR&VZp#MApx&n?tyt?0Dj+B>c;Tlb(U+T7P*mU7_CQ05+n@zWkq!SX(W7WiJ9PCzyOs3m^DrTIH145ouWSxQy>X zH2P@)5Z?`>C?D4vBADzP{y!D!lZH6pAgs zA9m}+V+G?2Sm%oJMY}7D+6(n>4g&rEgo>_jReDa@WlIIzgjKz3lJI+I%uZ-)(dkmG z6zqC|s{SS3vu+xYo{Ndw4o{B~N;sH@ZTaPe1!QhW)Mp3iQ0LqVh|~`m!@oLYVTQ+7 z8sglKwPtKmdfgl!ZQJ8vx-PY6d7*>4av)|4-l=r@k_CqfZCLc8*b{7E*)^ee{MmTt z3QaQgyL0%CShbgZs4_rvYMhRg`wp=~x@H`ULR-|PX<|M%y!1%H@UrbP^=>a@cOVER zAF1$Z7JqU0JY~Y_=|qR@;G|h&?-d=BM)jEd8w=@-O=57nRbCP~O5UR4FWV1U?3VkH42t%6~VH zQ8lt3?@Uyvnw5t)&YHiXHs;&*NlSSw^o`49OSz6RW;cAkr1#gSZBwEj=u)TL90}CY zjGCR9q2nZt*HS_FjRyUK|184Qpa9cz>j@ugHr(DyReq-}JeWnr+N=F%qK$;hzqa?p zD*krejqUxdxxBVGZsy$!&j?vevDu2Gy^uq8m~P6b(qV$WomngwI;Kc=tn;nK$Cr>@ zT?eVdYn#ej{gx1RCYFzq*`Qr6DcS1#RKu9MKJVeFIO99x?EvA1m&jX&F3bYg=^`PeQm!)m3x#E+qU>cj`^z$H%>7? zxF43*GAF+nB(BxUN}%s%_mc_<%(RI|!4l)65t42WgpsZ?bqo&K{t^jsJM0Y}nW!I& zd-p+D2IZBGmh&;cg@BmZ?lF3w z5gi{h<5>v$D)o54H#8*VvDdP4js6W+YYma(Hm`&fqwLF_9&hE&CqmFvnSVswBYpC#GQ+U(1tWb+lma))eF$>8r@g6JFZA(q6)`Qv ztp2kvmlaB$TOEE9t4W^an}5POg^L42(Eh_sY_%hU884k(2v=Px}-4h>zP<1hn)`t2cJp zxHIlAa7_292lEO0Y8YWEl9r^a^k+_M>XLoG?9u%38jFhr;t1Icq@$9x$8XG>#jqT=Zwsb$O-cB0Xp#r=NdQ$vX+X&&TZs5H^j} zlT%Pdj8tEZ+)C?PMyXr_gI*6J@TchIEqWN`HnVOQ(Qz}k0^*c-=b^L?vmeKmTPR*4 zkdGU1$R)Z{X|kvJE!=w;tMjcEdpW)3Du6>yiFh^hsdgD9uhrts;=bfB*7Od1Lj}45 zBXi8~&950Wj>H#^xF}+l5a48rG);P!tGz7tCg^MGwpw9vvOr5u{-mD=v`79*38bk= z&U>k0rVvx$@Q>*NSD04sH{P1VetqdYK!d90Qh{)8W-XM%VI5gQ6n8)LpVylsot$nE z1#D8y1xG@hhK?DSKGw80@a;hL`h756^6?DK0+J)Qj5zrx@<;QgUMHsuR22;7XMA3p zebr<{qn`VhcFUTUk8=_W0o$ zSFTM}ObLQ$2#e74XuZ@aBibBjIy^H!;LB7U3=>a$GI3vCv8Aw#82NVX&CqRp8>cno zeFDhGTDeyUco*H_L*p+9zC1Iwf=wG@p)r_@Zc6MJs;deOm%4nKv3K!#$t#TBec3C-0H`{F;x?XNT!b*Ew<23~CL8NfT_x^3Pyd&l?!YhiAA-trv#KEtVfe%-~7)20iOv4J*|{Y)I08N z|FN&#zbmNh%b3k)r_Y!@(k3516lT2k{dQ4+x?%z(2mJY05=6XSi`!6dr8M(lU6<=e z0uy&0Oj+rXUnH9x(cZRN8|Nd@fE@+nbE@2f_aNzeSg4tU*ZK<=CFXsOI_~ONW?G09 z;*H>#w#t+J1`a(8qK3&=Y9?IsP^=(u-U^jk(%huoXqUW zZrQuL6g^V2E(y{<{{$GyadQ`FShsUN6b;%XnwGuHl3_;mn!VLHK{wL-f1dHl;Dfu7 zxu%^w^E^j8cPUkc=x0IYk0lpB-=&rW;;khjN+d}aBUgKQSG0B0!np9& zOjY3NB2nDMbJS7-?gcm!XA>cA&m+*{tM`=L?gFZw#J8e=2RiXPW^~J`7*WiiHCRZW zANa;Ew7a7f5+Iz0z74gpSysMt=dBH$Y&)mY6Q3O^MzgN?Y5+@c^|d9UqsI2`I;2ck zWR>CCFZ}z8Lz`GMyB5d+U>$ku?c|_%VM!a<}+_fCLw)29+X5q`nRFSBB9{+&I@t1grWH+D{1Zd%q>rt$cCo(n-=U9B+#3l95# zGzl-?IX4ZA*){2S#1NQYSnbM)AxY@i6hYR5D=+@Z4xZBVLw{q4(hq<5E&i{hiD z_rM+G3vzlm<(}-u27}wqUgh0L`<1HRB0819q#ZZud-LFtk zd_bt1+rj6Jgvo}?A;mkN)uEZXrY_FQMD&ia8KFnEC@JN9HH%t>#o!+gr+vHowJ+(dTa$Kg;etOZK0~yL8@cZ z9HbX9N3QB&s7{YLV2L^oQLZDP!fwgo^B|6?gTVRz8i7J*FM0%$)4tz-*2;|f?R!fP zrx-*Ak;vRq8#_GEN&P;k_OmcxKZFH|boBS8E4JW}ER;~u^E@=wac3c1YSr~#O>J^{ z_*yro2t)?Tnm6!g=BY#9mG!gG1`v^z7HSjoTB{2UiFyon2fuK29zj!$2TLOkb{>FV z35UZ>CXM1OP{$z3O(5VZTYiHULS)2u{R<8OXE$g;WJP}d3$mIDgzP;d=zS0A6CaLjD|RUy z^qRZ7`-Bu+(lW3GpRW$ib5J4;*g92^M)IGx$yJBchul;!AECelz$fm4fXUC+Zvt%o zvPq}EWb){I0+Ra@*dt+ymdj_p7=!}qNe;NVOP)%*YiMo_na}^lek+k4prMsp1@1Du zaji^ETvGsI?3wT2JPRe#0gerY-CPPvS7m{-JXRIkq|!_=FhHZ>skE)~4hpZskt!-3 z4?bUZ)563{2(;yt!)bQR;_!x zDB6AE+2GY9M3qv~OGn>9bsj}@Se*SP0PU`8;10D{>h{p1WQY+6ufsQ&nzu_$04ZVHqf*6bH2B;mqF z6*3hZ$wc3PZtyWc2HH29b*xa3Ugh}P-SwrlMZh0)16nOn2cdT0>yL^kjPi;Nx%nV% z4>w0KL+!wg`^4S*V|rRBn?0|4IJu!j;K#WZHHCB_0xfrHSnSMtc)`=R2$?&T?lnNO zM{X6I5=l50SBJ8P2rmf`g1Hiid{5eMEAu?XM^43s>lY&q5(0jin*!bddk%+Y9>FEr zh7WwBk#hpB`B_}htz}@Gdi7MQB?<+#gS4ej47^f7;OUrS+MV?frELceQ{@ET?$BF; zEjV?y{ZxO#62v?NxC)luqybzl*!uGq|48jlOg25D%@0*>2DfpZfD*ZYB!=J1T5IU{ z07*Wr*!^#G>?>>5c?zQVVP@rcE@2d6-U39KPNi|=szR!r1%JNl3R|KMKs~q{?fv2hWXt-SVxP`HY0=wjkvW63OM~zJ5 z!0yGMp#eK|`tGQ+ku7is)lRW-AgVcv3CaV>%?&NJ`D;K_zMLDjmFt4@2?%aUQ0mz?hyX#%S3&I)nwouCP;3ngc*m`6ROw43*htNl=q+(LIa-6bRle+@X7=Yzp#;?6Z9|klY`b z?~Lr&B>|9)(~R!jWkTAoX_EpOPqH*-tyg^7rHI~a{;UeU0Kh{}z?Ck}W6)y|0Roe4 z!w&-yJ6;?woy}`4+L6k1i&eGFD+)w_cC*|$X^OzS4}#kT<|rD6Xc0^YmPwyIUKBu! z>jP)_q{&RfI7(2f5vYt>nP z3tDgl-){6;p%|e&@E*FM&`CDq<(F<$KpY#Yc$7Whd5E*$`A-GGey=rfhBsm^1bX_t zVZg#}e4?WA+a7U|<})aq@32X4#goSTme$~6H3}gNi^+EBNijTjZ`_@+h7RURQ#YJl z<;LULYm2#s5uwooG4YKmdQM@jmho486Mx878bBcaTm30h_hS`~=Q7jp2}_hoHOMi! zRTVJG_w}poH}V}AOvaf|7CYlF8ri#9MRltF>d}}q`hc91Z3*O+fzR0HI!bFbap zADQ#X`4vHKZv}`nCk+9#!do7%<#q7exV)lb#9FazHaY|$3@Z|qKc-vXl=V>mhrK() zi$;@1-$g5warIrm{?IjjWK;eMuUua*_D zGlU>KX31`+zD=1z ztQ>A^%&yeOKs3<+5h7d6q<0?LcLuzoed+1*x84B6&Oq)kfK+7xG}blHkJVJmA}rAs zf|oY&f$ncX5Y0bM_ziqxZ39`rsIrMysfD&~Zk4{tF`!0eIqH ze()Luv3!iHwfUyMlLoG{ zE&-$u!se~fk9NGE0+elr^FEA37^cQP>@5cGgL?jHhpiR>X9|t-!Gg7Yrc@jW ze+2^VUxvHm0Q&0YEWyQrl!f@MD?ANEieL~~)HMalU%&6&eNy8mEU(~^0Afgdl_sVS z>3tp874>`KG7p?_GRXb@lQQs)Wr-cu=9r{AKD>4$s=xt68(OkIlKI|150)p(s^t^) zK(&9gKNCoov^4^s0Nn_y@{J2CETrQ_|HeIB#i)L7xspYR!QBzbfmk9WfoV5xqK#K*7A;WP zI{q?TBo*7iwWp-T!23sV=7ua7&@IXvT34sOsveIn8)FR(?**alY({$6 zHs1Al>M6(}>Q@D9Lsy%0_=V;LwYeyFwxnvg8RQDjW?g>LjBOtg8se0gweB*-8m3SZ7GZZXlliaNLco}|9DUVDr|PTbsj zvlb;p843Te8QAsOQ$96|q_gEp^Fd-a;Sz7v$w8YhpCWKli<)#Rb@LsBDp55@=gYgX zW-oyyd>bgru4T}%cbX`9&BX@^0>}pu*mTOK4_7BZvH^esLilA@!{slzwKw5*gHF*# zGR9x_W=BVX_o{kJY#la*5@WQFwt6vo0(+W`jjrq=RFx4=%w6T8B!X)F$&|#k`QHek zRKxtr94NbdJdhAy%hf+AM3$QOmOuWzIlPNYlZdx!c_Gt{#q3Xjh`Oyae8L#enSNh! zJK1c6&$#AoaVZ)a`D9bkuYkCtpcFpqLVk#88(SxQAivsNcT?IM{9Z`2R2MsO>Vk~^ z!sR6&(vzBf47j*gF^-p38}v^zRMSpibCTzxUPe=dH1>?Ldj(|XsX|RppMVm#kWNrX zhHF#NKRB*8(S#qwADGOInn|{9-P5bW7Nu%A>Q0hm}={DU1bqNvN+ zw4>$u4hIz0+T#3%CC#lS)1e9toniA7$VoUSf+OHcH)r7!GwP?29}+)f-+*QWFOMky z7`C?~Rw93Xly9bvZTu|cZ9F_K#ZGq113pMjtV?$3Y7}#yW?RG3)dchunVl{!=>g6& zCnLUE{SM`CqtoX|))2F6R^p#i=kYOUYZzI58d2K&k<0Ea0M^=bC*m+J1nTuxh9m12 z&s~qvi=4I=+7p!eXpq)^YD#jRhn>~7a`N80D*Gg3{qMeBk&Tx}o*W)=+eb%RZP&C# z%-2hM$Vy#oX!5vN$e6&-dpL&}rM)MxME>q@2mqo4f@+?ra~>)*6-GiWm z?S-S#@=Eo2`FGA+Fn>GyEHK0nofwz5BF*-aQJM+P8A`I5A@Fu+=W84k#IJo;gpvvo&(0-EfI$6T#wtWFEm@WLq+8Cgx08Q+?F&z{_XxC4eUSU6zd2 zu*GMuBbI`EjP%s>D^7Wv#4m+(?Z;gG-h8Dw9HFC1J=m+MdE{?UV-cNoS08rfXIpou zW~0>I_1LX0*40K)fb_0m>tGVTY_lx^oVlHPxi$?g=)PsYuc=afM$ky7>y(xN<23+B z4AAuSHjR6&@Lnmn8zlr0{sA+NXU9b>1qkg5v!x;;j^$p&Syz)K^7BW4lH=LFs zO0%JVSE?X7DC+^S>1DO*EYA?v`7BY7MnugvR@4_mqQCs+mFB(Y)&9CrRIss&`YH(o z4&^3)nNw+1r_dfBUN!_Egm2q^NlFl)@vXz3F*1vb_#|*8?DHB4%jj0u;|hVJo{Bc; zewVX2^n{AZ|LY%c4RaC{mHvc|;^oDx+V>kUM4s9s;klk*1s@j9ed3#lsMdAU$rBIt zlPe!9C>z!rewtc;yZ`uR`pXZ_TB+x$4^36~J=U_wsaI$5|8;MrkS_B@`GL4__63hC zg;$kzuLu1(N(eC!x$2ehnFr(p00QJL9@>l`;W0-NA>uoC`iMYGnYR_6F|8gx-)fH%uMd^EEBQqF{$b}cB8@HJC&-(Ln9 zhO1jOaRIihAE`FXpPzOZsou2#)dMQ==tbPbiodKN`dM{tOO}j&<&O+_! z?!Wjt@W1@pt~(7d=EWJ8)P4jJcs1SY%xXhIsl!*!JroJ|>6p+5=985x(gMYns6L?! zK|gI|-S4XFP~*j0%g#A{j){&IeZy>l`H$b zx&pQL4Ih_Xw5V_Tl$(#sEL%35N6f|+d9!&iEtYY#)`v2!H}riHNG>$H*JW2`6y}~{ z2fBs%zuPa&VDZOpBLXERf}XyzS(GazGZm1Bpv3`ypb9vQHqjTwLmlRd! zdyB^i`tH`n)s5dh5^sI)Sb+xqwB}IO`O_fRDXJ*Jjti;Al`)db9Xf}E8{v0_M9hKu z3JDqGYuXs|Q;D&abbfl@f@<%%o@@}jF(KglfOU|&cx3%G;p;Jw6y`My9v8`Jdbd6u zq!8@S8P%z0ob+bHwXwzP^y-F@V@z#@Pg@SfOw4W0Dxvat^n|O9w20m5+$6)^cfyF& zR8}p`hfR}K!d8Y@vOquO2cN@F<>81|riLS=hvug~^b34`HZ090YUs1dF0RxtR6C^e zxmDnN`0C5|B_4-lRTV|WTBXldS<33$CWA`fBI625P~9}+7kRAiEX_gVSYZ*315H2o zO-R!`U~bZ;-wME=z0Oy`lcY5gw(KbT_PK`V36BMXfti9iqa}{DX4mo{x!2*fCe!|L z&lU>wE63?IT^kQ-KG{NOI(1)pSL{(cS+?WDF zC}$-vA70zsQ2CCcs{UD{doFr;`%hfC2{2WbvU_8`wIZDNp|Mw`Z_#dpR-)8p9$C?1 z)}~uZ6X%|m9`CH2TvoX+GIC9X{lvR~i|l5UYi9&0CWE>+kBKiR$t&isd~jdc@>r1{ zmE-OJJOxVOIYi$=8zNJ-gl$BjD?b+-QU%dXVWa+SlCdq=Xc1TrCTtc>&~EuNszNn1gOo5INsgff$&#wyBoyFeijPcvr6R0 zpK6e+6YwJi?E{z`H|fux@E>jM7p`$l^pmSMJzqHhY zZRVs5(EBv|EZ9;n5RpD(D2A#1;PA83E^n$1l*cDk_V!>8k`(jYn=>%u&)Zlx3Rzih z&@tff@90RklyuHo*?B9vaFQNkz94BKZz-E@O*ZLy-D#OW?)3tHY>+y~X{+^{Hc6Ev zROGw6b||lE^O1VHLRNkih`G5*vc$AbW@Ql9e@O$=?t@iN}0=wfy}J5dUE@ zeF1Tqn(qCW1f$(PagD$k z$aVy`6jiYKGSibkBb~`h&vhdI=XLERTWR}f8@FW;v;#ROTzvY&+dK_hJk?q}>vKPD z9;|PW{#X^_gB+!GbkQG;9nwIZICc2vfXRk4>RHQzD~EJiWfV6Fm}m%`tQ*JARPt}l z#6^O>ON9xu$yrENh=)gXRju;NskHi+wNi~mKjXq-e7Mq$n*>_m+D!-i4zqY3A?@{| z{t{MjkK;St>WQzW3*rz`hgeF2bn;0jXX)xcO{)$R-12{I%ZN^}TNttf?Xx*|vcS9_ zGVeJOM{FybcrV^eRq>a=^LJm5L(R*FXxtHPi+Er05a}bnR@-|QT+`|>tG>h5nXfny zF?ep)7JbM=ENU}sVckts_iJvimvZiN0KM9zW|xrA_(=*1Ua03 zr~I46IcGoGPu9HVp@pR`JITI9LOX6u-V-jsOOC9teEngu_)Jo8roZ^N;IoRv>j{(l zi42d8laqC(S#T%TZkAs-6sCF_eL>?d1LoQAr<^&Nhco{74xnH5=2gpXmz|i8G#^0o zbGmXm-h7k5w&sh}!h^y&rLPg)s_*FTMh)o`U zhc`{j>~}i5y7Zxx4_mjj=-2XR{R2@8gQNKcBS&IMTNR4BYwjOUZXmb!rjLSR`>Vh@$e62J z0k~Rdp^Le)T0b6<66ar4*eAYticMzLi*1M$yFc#lXKn7`{i4NZo4VhF$(ynpHqB&g_?DWp3;Y6egqaH)Z!^7jRu7C$r*L%4D*AEys6wJ8fL zSpnLi05B@(nA6Ugi;IIt&z)npNP)zQvUf*j)Z2|G1#uB612im47XYZEizX=+t3v*- zK7iIALKdKrZEEeR`JbxM|L|G>bKO#^xQ6+G^aiIW zJ_Fq4<1IGF{cHNo$*yG);%Ui&NJviOC&@8%#3m3tDOl$&-CWKA0K@2QAPlKYLjvGv zARIRkZUbSos)Kc?KRBSAFF zWxo1P(qQ!C#LeC1VUZM_jsg!rLc+JsVn?q2L8jc>;}F2--~WT(plU9KbKf;#Y;2Ae z(%A!cN_O>lNf*Fm?zM)pyHZzVIMFhFor3dR;ip8UEC?t%eeWV_k34ekM4@$Jz?1ykD;VA>4RlI@$4 z|3Q?pP3E!!8@#^2Hnt{SCYz_s3U^@2``hjn0^Wl$gsN1uJwg_=Dwl$NjO>6PKK&A} z<6cLfL;O(}E@ z0;p$Kr2>o>?trcOFrb|RC7VtB2+de*=PbkN!!T*%68}2z2XKosTC3M`2d_2x8!DAq zNw1>Y`w{Jgz=L496jzfh4)>$*F*_8o4nceSN|~7VH|Pd?Wux5?vfJ}wB?_{J_V(FN zhV7!!pV%EUijX3h4VE2{nflTe)1-wsCcVtCJEW*dd0m858O~7J!Mc^fWnbWbB0N5V zJ_z7rcyPE)=Fe4=eg<3phmgyzrE7zRy`p}J{0@w60U(T?f1UII;dqdiRL6lLtX>Q8 zqh9#UR$5gzXEp8&jO~J6nqEf%=8*tmyDWkBio;O7hC5ypET4(tZ2xZ}^|hyVe%fr?{o;K+>X!`G=dhWvpagES_8bIN_5XTLeT+r=*sD_Ll| z+!vD&Gq_g(k!_ZUS%6Vs>PE$ZKsRupN9}%3T;YE%KMhFA2VeQuQg|!}QdS)Pp5}6_ z@wggr{Q7zehvuHNLORiS&?l@O85n4lzaMu(XzWH=5mIg+&q08k%3gBGMn*jr?JPJ2e|K;vEo_FAVl*v@vnqEDfIk%o$u_Pu z%7HxpH2j^r1Ab@jm^Ln>VC$3+#Jj!c|N90V}mbQZVl=kq+p@i*$0#UBTJa=}3=>N26In%tx3OLvg zhR^o5Z%^qg9h&Z|sJn#_!7#mCSy0(lu7AJF)+?jMbJZNXjQ96W!lG3P^cN)kvr$1e zVCFr0d~Amq+b_}wqntf+OFLAIOIu`s1#&os_rjl^c(Shiimf|=p&hl;J%yGz4jb0# zl4)lw)_yJ=w{<{&AN;+AXQXX5cD_#l8Yz3RGwIyK961fJH>hF~so&*4xYqi*^3YPq zj&iAKv#@eYb~?uFy1XMp4iFR9 zKDDFByU9L5=ys*dk!=YjKV?(vV7s=cP3;&>dZDk9!9Hb|b9bILbY*Qv?eoDN zWZz*NV7YAAMCWPEf;)U5j{eNHf_v+15yTG}wL6-GPF(^V5p^dd_rjl&ct-ZW9{PZw z24%#V-M$WcpHl5$QnA-jgP@(?%?gZ)p{S>C=KmAu0oxSG4%S^(=kWiG##0$5?UIAM zJkH?ZEC&eho7PD!qkMsN8Bm+tSz7P9)sTldT5Y}m$kGfB-v7V9MHyFgUk@P-^rTMA zbR*#JQIZ`$IeX0mDP`B@%(tE7Q`84UuZ#;L&b=ibuR*u{JxWVTxzW0zoKczv-L~K@ zlWag&5zGN&4;S%m2_7EjD5tG1Y2ML&B?V|gP7&B0aL6*Eo~w2U7(&1wlj*0lt!V=i z7k{S{{t4GnI_EgYg2O(!B+2#I75=uY=JxcjzAXi?qe|s}D=u+w@0!pihfENa>hQry zLgq3ZIOorZLMGX=t|#$J>&t(+w>4NBoPLI1ilJlRa%5T}7Q*XF|M%z#sXWN;k5v89e=e7&~M$ literal 0 HcmV?d00001 diff --git a/forge.config.js b/forge.config.js new file mode 100644 index 0000000..bcc4417 --- /dev/null +++ b/forge.config.js @@ -0,0 +1,80 @@ +const path = require('path'); +const package = require('./package.json'); + +module.exports = { + hooks: { + postPackage: require('./tools/notarize') + }, + packagerConfig: { + asar: false, + icon: path.resolve(__dirname, 'assets', 'icon'), + appBundleId: 'com.felixrieseberg.macintoshjs', + appCategoryType: 'public.app-category.developer-tools', + win32metadata: { + CompanyName: 'Felix Rieseberg', + OriginalFilename: 'macintosh.js' + }, + osxSign: { + identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)', + 'hardened-runtime': true, + 'gatekeeper-assess': false, + 'entitlements': 'static/entitlements.plist', + 'entitlements-inherit': 'static/entitlements.plist', + 'signature-flags': 'library' + }, + ignore: [ + /\/assets(\/?)/, + /\/docs(\/?)/, + /\/tools(\/?)/, + /package-lock\.json/, + /README\.md/, + /CREDITS\.md/, + /issue_template\.md/, + /HELP\.md/, + ] + }, + makers: [ + { + name: '@electron-forge/maker-squirrel', + platforms: ['win32'], + config: (arch) => { + return { + name: 'macintosh.js', + authors: 'Felix Rieseberg', + exe: 'macintoshjs.exe', + noMsi: true, + remoteReleases: '', + setupExe: `macintoshjs-${package.version}-setup-${arch}.exe`, + setupIcon: path.resolve(__dirname, 'assets', 'icon.ico'), + certificateFile: process.env.WINDOWS_CERTIFICATE_FILE, + certificatePassword: process.env.WINDOWS_CERTIFICATE_PASSWORD + } + } + }, + { + name: '@electron-forge/maker-zip', + platforms: ['darwin', 'win32'] + }, + { + name: '@electron-forge/maker-deb', + platforms: ['linux'] + }, + { + name: '@electron-forge/maker-rpm', + platforms: ['linux'] + } + ], + publishers: [ + { + name: '@electron-forge/publisher-github', + config: { + repository: { + owner: 'felixrieseberg', + name: 'macintosh.js' + }, + draft: true, + prerelease: true + } + } + ] +}; diff --git a/package.json b/package.json index 79f74b7..5d20e57 100644 --- a/package.json +++ b/package.json @@ -19,34 +19,11 @@ }, "license": "MIT", "config": { - "forge": { - "packagerConfig": {}, - "makers": [ - { - "name": "@electron-forge/maker-squirrel", - "config": { - "name": "macintosh" - } - }, - { - "name": "@electron-forge/maker-zip", - "platforms": [ - "darwin" - ] - }, - { - "name": "@electron-forge/maker-deb", - "config": {} - }, - { - "name": "@electron-forge/maker-rpm", - "config": {} - } - ] - } + "forge": "./forge.config.js" }, "dependencies": { - "electron-squirrel-startup": "^1.0.0" + "electron-squirrel-startup": "^1.0.0", + "update-electron-app": "^1.5.0" }, "devDependencies": { "@electron-forge/cli": "6.0.0-beta.52", diff --git a/src/basilisk/BasiliskII-worker-boot.js b/src/basilisk/BasiliskII-worker-boot.js index 967ed2c..a1acfe3 100644 --- a/src/basilisk/BasiliskII-worker-boot.js +++ b/src/basilisk/BasiliskII-worker-boot.js @@ -62,10 +62,22 @@ function addAutoloader(module) { true ); } catch (error) { + postMessage("showMessageBoxSync", { + type: 'error', + title: 'Could not transfer file', + message: `We tried to transfer ${fileName} to the virtual machine, but failed. The error was: ${error}` + }); + console.error(`loadDatafiles: Failed to preload ${fileName}`, error); } }); } catch (error) { + postMessage("showMessageBoxSync", { + type: 'error', + title: 'Could not transfer files', + message: `We tried to transfer files to the virtual machine, but failed. The error was: ${error}` + }); + console.error(`loadDatafiles: Failed to copyFilesAtPath`, error); } } @@ -115,6 +127,12 @@ function writeSafely(filePath, fileData) { return new Promise((resolve) => { fs.writeFile(filePath, fileData, (error) => { if (error) { + postMessage("showMessageBoxSync", { + type: 'error', + title: 'Could not save files', + message: `We tried to save files from the virtual machine, but failed. The error was: ${error}` + }); + console.error(`Disk save: Encountered error for ${filePath}`, error); } else { console.log(`Disk save: Finished writing ${filePath}`); @@ -158,6 +176,12 @@ async function saveFilesInPath(folderPath) { ); } } catch (error) { + postMessage("showMessageBoxSync", { + type: 'error', + title: 'Could not safe file', + message: `We tried to save the file "${file}" from the virtual machine, but failed. The error was: ${error}` + }); + console.error(`Disk save: Could not write ${file}`, error); } } diff --git a/src/main/devmode.js b/src/main/devmode.js index a9d710b..83176de 100644 --- a/src/main/devmode.js +++ b/src/main/devmode.js @@ -1,23 +1,26 @@ -const fs = require('fs'); -const path = require('path'); -const { app } = require('electron'); +const fs = require("fs"); +const path = require("path"); +const { app } = require("electron"); -const appDataPath = app.getPath('userData'); -const devFilePath = path.join(appDataPath, 'developer'); +const appDataPath = app.getPath("userData"); +const devFilePath = path.join(appDataPath, "developer"); -let isDevMode = true; +let isDevMode; function getIsDevMode() { if (isDevMode !== undefined) { return isDevMode; } - return isDevMode = fs.existsSync(devFilePath); + return (isDevMode = !app.isPackaged || fs.existsSync(devFilePath)); } function setIsDevMode(set) { if (set && !getIsDevMode()) { - fs.writeFileSync(devFilePath, `So you're a developer, huh? Neat! Welcome aboard!`); + fs.writeFileSync( + devFilePath, + `So you're a developer, huh? Neat! Welcome aboard!` + ); } else if (!set && getIsDevMode()) { fs.unlinkSync(devFilePath); } @@ -27,5 +30,5 @@ function setIsDevMode(set) { module.exports = { getIsDevMode, - setIsDevMode + setIsDevMode, }; diff --git a/src/main/index.js b/src/main/index.js index d241ff7..68a978a 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,39 +1,54 @@ const { app, BrowserWindow } = require("electron"); -const path = require("path"); const { registerIpcHandlers } = require("./ipc"); const { createWindow } = require("./windows"); +const { getIsDevMode } = require("./devmode"); +const { shouldQuit } = require("./squirrel"); +const { setupUpdates } = require("./update"); -// Handle creating/removing shortcuts on Windows when installing/uninstalling. -if (require("electron-squirrel-startup")) { - // eslint-disable-line global-require - app.quit(); -} +async function onReady() { + if (!getIsDevMode()) process.env.NODE_ENV = "production"; -// This method will be called when Electron has finished -// initialization and is ready to create browser windows. -// Some APIs can only be used after this event occurs. -app.on("ready", () => { registerIpcHandlers(); createWindow(); -}); + setupUpdates(); +} -// Quit when all windows are closed, except on macOS. There, it's common -// for applications and their menu bar to stay active until the user quits -// explicitly with Cmd + Q. -app.on("window-all-closed", () => { +/** + * All windows have been closed, quit on anything but + * macOS. + */ +function onWindowsAllClosed() { + // On OS X it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== "darwin") { app.quit(); } -}); +} -app.on("activate", () => { +function onActivate() { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } -}); +} -// In this file you can include the rest of your app's specific main process -// code. You can also put them in separate files and import them here. +function main() { + // Handle creating/removing shortcuts on Windows when + // installing/uninstalling. + if (shouldQuit()) { + app.quit(); + return; + } + + // Set the app's name + app.setName("macintosh.js"); + + // Launch + app.on("ready", onReady); + app.on("activate", onActivate); + app.on("window-all-closed", onWindowsAllClosed); +} + +main(); diff --git a/src/main/ipc.js b/src/main/ipc.js index e6d309f..5da0514 100644 --- a/src/main/ipc.js +++ b/src/main/ipc.js @@ -1,5 +1,6 @@ -const { ipcMain, app, BrowserWindow } = require("electron"); +const { ipcMain, app, BrowserWindow, dialog } = require("electron"); const { setIsDevMode, getIsDevMode } = require("./devmode"); +const { getMainWindow } = require("./windows"); function registerIpcHandlers() { ipcMain.handle("quit", () => app.quit()); @@ -12,9 +13,23 @@ function registerIpcHandlers() { ipcMain.handle("getIsDevMode", () => getIsDevMode()); - ipcMain.handle("setIsDevMode", (event, set) => { + ipcMain.handle("setIsDevMode", (_event, set) => { setIsDevMode(set); }); + + ipcMain.handle("showMessageBox", (_event, options) => { + const mainWindow = getMainWindow(); + return dialog.showMessageBox(mainWindow, options); + }); + + ipcMain.handle("showMessageBoxSync", (_event, options) => { + const mainWindow = getMainWindow(); + return dialog.showMessageBoxSync(mainWindow, options); + }); + + ipcMain.handle("getAppVersion", () => { + return app.getVersion(); + }); } module.exports = { diff --git a/src/main/squirrel.js b/src/main/squirrel.js new file mode 100644 index 0000000..d403283 --- /dev/null +++ b/src/main/squirrel.js @@ -0,0 +1,7 @@ +function shouldQuit() { + return require("electron-squirrel-startup"); +} + +module.exports = { + shouldQuit, +}; diff --git a/src/main/update.js b/src/main/update.js new file mode 100644 index 0000000..1a11172 --- /dev/null +++ b/src/main/update.js @@ -0,0 +1,14 @@ +const { app } = require("electron"); + +function setupUpdates() { + if (app.isPackaged) { + require("update-electron-app")({ + repo: "felixrieseberg/macintosh.js", + updateInterval: "1 hour", + }); + } +} + +module.exports = { + setupUpdates, +}; diff --git a/src/main/windows.js b/src/main/windows.js index 399e6f6..992e806 100644 --- a/src/main/windows.js +++ b/src/main/windows.js @@ -6,6 +6,10 @@ const { getIsDevMode } = require("./devmode"); const windowList = {}; let mainWindow; +function getMainWindow() { + return mainWindow; +} + function handleNewWindow(event, url, frameName, disposition, options) { // open window as modal event.preventDefault(); @@ -85,4 +89,5 @@ function createWindow() { module.exports = { createWindow, + getMainWindow, }; diff --git a/src/renderer/audio.js b/src/renderer/audio.js index f0876b3..dcc11c9 100644 --- a/src/renderer/audio.js +++ b/src/renderer/audio.js @@ -4,9 +4,7 @@ var audio = { channels: 1, bytesPerSample: 2, samples: 4096, - // freq: 11025, freq: 22050, - // freq: 44100, format: 0x8010, paused: false, timer: null, @@ -41,12 +39,6 @@ var audioDataBuffer = new SharedArrayBuffer(AUDIO_DATA_BUFFER_SIZE); var audioDataBufferView = new Uint8Array(audioDataBuffer); var audioContext = new AudioContext(); -// document.querySelector('#enableAudio').addEventListener('click', function() { -// audioContext.resume().then(() => { -// document.querySelector('#enableAudio').remove(); -// }); -// }); - var gainNode = audioContext.createGain(); gainNode.gain.value = 1; @@ -120,11 +112,6 @@ function openAudio() { audio.gotFirstBlock && Date.now() - getBlockBufferLastWarningTime > 5000 ) { - // console.warn( - // `UI thread tried to read audio data from worker-locked chunk ${getBlockBufferWarningCount} times` - // ); - //console.log("curChunkIndex", curChunkIndex); - // debugger getBlockBufferLastWarningTime = Date.now(); getBlockBufferWarningCount = 0; } @@ -139,10 +126,7 @@ function openAudio() { curChunkAddr + 2 + audio.bufferSize ); audio.nextChunkIndex = audioDataBufferView[curChunkAddr + 1]; - // console.assert(audio.nextChunkIndex != curChunkIndex, `curChunkIndex=${curChunkIndex} == nextChunkIndex=${audio.nextChunkIndex}`) audioDataBufferView[curChunkAddr] = LockStates.EMUL_THREAD_LOCK; - // debugger - // console.log(`got buffer=${curChunkIndex}, next=${audio.nextChunkIndex}`) return blockBuffer; }; @@ -196,7 +180,6 @@ function openAudio() { // And queue it to be played after the currently playing audio stream. audio.pushAudio(blockBuffer, audio.bufferSize); } - // console.log(`queued ${i} buffers of audio`); }; // Create a callback function that will be routinely called to ask more audio data from the user application. diff --git a/src/renderer/controls.js b/src/renderer/controls.js index 44f212a..8913b95 100644 --- a/src/renderer/controls.js +++ b/src/renderer/controls.js @@ -1,8 +1,9 @@ const { quit, devtools } = require("./ipc"); const { getIsWorkerRunning, getIsWorkerSaving } = require("./worker"); const { showCloseWarning } = require("./dialogs"); +const { getIsDevMode } = require("./ipc"); -function registerControls() { +async function registerControls() { document.querySelector("#close").addEventListener("click", () => { if (!getIsWorkerRunning()) { quit(); @@ -16,6 +17,10 @@ function registerControls() { document.querySelector("#devtools").addEventListener("click", () => { devtools(); }); + + if (await getIsDevMode()) { + document.querySelector("#devtools").classList.remove("hidden"); + } } registerControls(); diff --git a/src/renderer/credits.html b/src/renderer/credits.html index 29f4d70..6a3763f 100644 --- a/src/renderer/credits.html +++ b/src/renderer/credits.html @@ -8,6 +8,9 @@

Credits

+ + +

This app by Felix Rieseberg. The real work was done by the people below:

@@ -29,14 +32,6 @@

Basilisk II and its components are released under the GNU GPL. See LICENSE for details.

- + \ No newline at end of file diff --git a/src/renderer/credits.js b/src/renderer/credits.js new file mode 100644 index 0000000..dc8c9e2 --- /dev/null +++ b/src/renderer/credits.js @@ -0,0 +1,19 @@ +const { shell, ipcRenderer } = require("electron"); +const path = require("path"); +const { versions } = require("process"); + +const { getAppVersion } = require("./ipc.js"); + +async function credits() { + license.onclick = () => { + const licensePath = path.join(__dirname, "../basilisk/LICENSE.txt"); + shell.openPath(licensePath); + }; + + const version = await getAppVersion(); + document.querySelector( + "#versions" + ).innerHTML = `macintosh.js v${version} with Electron v${process.versions.electron}`; +} + +credits(); diff --git a/src/renderer/help.html b/src/renderer/help.html index 25af978..46a236b 100644 --- a/src/renderer/help.html +++ b/src/renderer/help.html @@ -9,21 +9,24 @@

Help

-

Passing files into the machine

+

How can I get files into the machine?

  • Open the folder "macintosh.js" in your user directory.
  • Put any files you want to use in your VM (virtual machine) into that folder.
  • Restart the app.
  • -
  • On the VM's (virtual machine) desktop, find the "Unix" volume and double-click to open it.
  • +
  • On the VM's desktop, find the "Unix" volume and double-click to open it.
  • Find the "macintosh.js" folder, which now contains all your files.
- Files will be copied over when you start your VM (virtual machine). They are not synchronized while the VM is running. However, any changes made to the "macintosh.js" folder in your VM will be saved to the corresponding folder in your home directory once you shut the VM down. + Files will be copied over when you start your VM. They are not synchronized while the VM is running. However, any changes made to the "macintosh.js" folder in your VM will be saved to the corresponding folder in your home directory once you shut the VM down. + + Be chill about it: The more files you put into that folder, + the more memory macintosh.js will consume.

-

Getting files out of machine

+

How can I get files out of the machine?

    @@ -43,8 +46,6 @@

    - + \ No newline at end of file diff --git a/src/renderer/help.js b/src/renderer/help.js index 83e8ca6..1bbff18 100644 --- a/src/renderer/help.js +++ b/src/renderer/help.js @@ -1,35 +1,47 @@ -const { shell, ipcRenderer } = require('electron'); -const path = require('path'); -const fs = require('fs'); -const homedir = require('os').homedir(); -const macDir = path.join(homedir, 'macintosh.js'); +const { shell, ipcRenderer } = require("electron"); +const path = require("path"); +const fs = require("fs"); +const homedir = require("os").homedir(); +const macDir = path.join(homedir, "macintosh.js"); let isDevTools; // Setup dev mode function fetchIsDevTools() { - ipcRenderer.invoke('getIsDevMode').then((result) => { + ipcRenderer.invoke("getIsDevMode").then((result) => { isDevTools = result; if (result) { - devtools.innerHTML = 'Disable developer tools'; + devtools.innerHTML = "Disable developer tools"; } else { - devtools.innerHTML = 'Enable developer tools'; + devtools.innerHTML = "Enable developer tools"; } }); } -user_dir.onclick = user_dir2.onclick = () => { - if (!fs.existsSync(macDir)) { - fs.mkdirSync(macDir); - } +async function help() { + user_dir.onclick = user_dir2.onclick = () => { + try { + if (!fs.existsSync(macDir)) { + fs.mkdirSync(macDir); + } - shell.showItemInFolder(macDir); -} + shell.showItemInFolder(macDir); + } catch (error) { + ipcRenderer.invoke("showMessageBox", { + type: "error", + title: "Could not open folder", + message: `We tried to open the macintosh.js directory, but failed. The error was: ${error}`, + }); + } + }; + + devtools.onclick = async () => { + await ipcRenderer.invoke("setIsDevMode", !isDevTools); + fetchIsDevTools(); + }; -devtools.onclick = async () => { - await ipcRenderer.invoke('setIsDevMode', !isDevTools); fetchIsDevTools(); } -fetchIsDevTools(); +help(); diff --git a/src/renderer/index.html b/src/renderer/index.html index 959fd47..d4e885a 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -21,7 +21,7 @@ Quit Credits Help - Dev +