<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://flashpointarchive.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=XXLuigiMario</id>
	<title>Flashpoint Datahub - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://flashpointarchive.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=XXLuigiMario"/>
	<link rel="alternate" type="text/html" href="https://flashpointarchive.org/datahub/Special:Contributions/XXLuigiMario"/>
	<updated>2026-10-17T19:10:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=File:QEMU-FP.png&amp;diff=5139</id>
		<title>File:QEMU-FP.png</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=File:QEMU-FP.png&amp;diff=5139"/>
		<updated>2021-05-18T14:31:05Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: XXLuigiMario uploaded a new version of File:QEMU-FP.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=File:QEMU-FP.png&amp;diff=5138</id>
		<title>File:QEMU-FP.png</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=File:QEMU-FP.png&amp;diff=5138"/>
		<updated>2021-05-18T14:27:16Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: XXLuigiMario uploaded a new version of File:QEMU-FP.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=5137</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=5137"/>
		<updated>2021-05-18T14:08:48Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, instead, when a file lookup fails, the request is proxied to a fallback server to allow loading files for Legacy games. This is the Legacy Apache server in the case of Flashpoint Ultimate or the PHP router in the case of Flashpoint Infinity.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/&amp;lt;code&amp;gt;[device]&amp;lt;/code&amp;gt;: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[device_serial_code]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP from an attached block device into the virtual htdocs.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Finds the attached block device with the specified serial.&lt;br /&gt;
&lt;br /&gt;
If no device was found with this serial, it checks again once every 100 ms.&lt;br /&gt;
If no matching device was found after 10 seconds, &amp;quot;NO_SUCH_FILE&amp;quot; is returned.&lt;br /&gt;
&lt;br /&gt;
2. A symbolic link is created from &amp;lt;code&amp;gt;/dev/[device]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[device].zip&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is done in order to trick AVFS into thinking that the block device is a regular ZIP file.&lt;br /&gt;
AVFS can transparently access ZIP files as a folder by appending a pound sign after the filename.&lt;br /&gt;
An AVFS mount of the root directory exists in &amp;lt;code&amp;gt;/root/.avfs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/root/.avfs/tmp/[device].zip#&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[device]&amp;lt;/code&amp;gt; as a case-insensitive mirror using fuzzyfs&lt;br /&gt;
&lt;br /&gt;
fuzzyfs is a read-only filesystem that allows case-insensitive access to files.&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/[device]/content&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
This is done by unmounting &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt; then re-mounting with a new set of settings.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
'''[https://drive.google.com/file/d/1pnbA9l4E0vi0EhmeO9Qi64ifvSbHShjF/view?usp=sharing Download Fresh Alpine Linux image (Updated: 2020-09-21)]'''&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://go.nul.sh/fpultimate -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
For Infinity use: https://go.nul.sh/fpinfinity&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Technologies]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=5136</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=5136"/>
		<updated>2021-05-18T14:07:53Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, instead, when a file lookup fails, the request is proxied to a fallback server to allow loading files for Legacy games. This is the Legacy Apache server in the case of Flashpoint Ultimate or the PHP router in the case of Flashpoint Infinity.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/&amp;lt;code&amp;gt;[device]&amp;lt;/code&amp;gt;: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[device_serial_code]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP from an attached block device into the virtual htdocs.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Finds the attached block device with the specified serial.&lt;br /&gt;
&lt;br /&gt;
If no device was found with this serial, it checks again once every 100 ms.&lt;br /&gt;
If no matching device was found after 10 seconds, &amp;quot;NO_SUCH_FILE&amp;quot; is returned.&lt;br /&gt;
&lt;br /&gt;
2. A symbolic link is created from &amp;lt;code&amp;gt;/dev/[device]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[device].zip&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is done in order to trick AVFS into thinking that the block device is a regular ZIP file.&lt;br /&gt;
AVFS can transparently access ZIP files as a folder by appending a pound sign after the filename.&lt;br /&gt;
An AVFS mount of the root directory exists in &amp;lt;code&amp;gt;/root/.avfs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/root/.avfs/tmp/[device].zip#&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[device]&amp;lt;/code&amp;gt; as a case-insensitive mirror using fuzzyfs&lt;br /&gt;
&lt;br /&gt;
fuzzyfs is a read-only filesystem that allows case-insensitive access to files.&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/[device]/content&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
This is done by unmounting &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt; then re-mounting with a new set of settings.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
'''[https://drive.google.com/file/d/1pnbA9l4E0vi0EhmeO9Qi64ifvSbHShjF/view?usp=sharing Download Fresh Alpine Linux image (Updated: 2020-09-21)]'''&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://go.nul.sh/fpultimate -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
For Infinity use: https://go.nul.sh/fpinfinity&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Technologies]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=5135</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=5135"/>
		<updated>2021-05-18T14:05:31Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, instead, when a file lookup fails, the request is proxied to a fallback server to allow loading files for Legacy games. This is the Legacy Apache server in the case of Flashpoint Ultimate or the PHP router in the case of Flashpoint Infinity.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/&amp;lt;code&amp;gt;[device]&amp;lt;/code&amp;gt;: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[device_serial_code]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP from an attached block device into the virtual htdocs.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Finds the attached block device with the specified serial.&lt;br /&gt;
If no device was found with this serial, it checks again once every 100 ms.&lt;br /&gt;
If no matching device was found after 10 seconds, &amp;quot;NO_SUCH_FILE&amp;quot; is returned.&lt;br /&gt;
&lt;br /&gt;
2. A symbolic link is created from &amp;lt;code&amp;gt;/dev/[device]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[device].zip&amp;lt;/code&amp;gt;&lt;br /&gt;
This is done in order to trick AVFS into thinking that the block device is a regular ZIP file.&lt;br /&gt;
AVFS can transparently access ZIP files as a folder by appending a pound sign after the filename.&lt;br /&gt;
An AVFS mount of the root directory exists in &amp;lt;code&amp;gt;/root/.avfs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/root/.avfs/tmp/[device].zip#&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[device]&amp;lt;/code&amp;gt; as a case-insensitive mirror using fuzzyfs&lt;br /&gt;
fuzzyfs is a read-only filesystem that allows case-insensitive access to files.&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/[device]/content&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
This is done by unmounting &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt; then re-mounting with a new set of settings.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
'''[https://drive.google.com/file/d/1pnbA9l4E0vi0EhmeO9Qi64ifvSbHShjF/view?usp=sharing Download Fresh Alpine Linux image (Updated: 2020-09-21)]'''&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://go.nul.sh/fpultimate -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
For Infinity use: https://go.nul.sh/fpinfinity&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Technologies]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3102</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3102"/>
		<updated>2020-09-21T13:31:31Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, so an FTP server runs on the host to share needed files.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/htdocs: (Initially unmounted) Contains the contents of the existing merged htdocs, for non-GameZIP games.&lt;br /&gt;
* /tmp/_&amp;lt;code&amp;gt;[game]&amp;lt;/code&amp;gt;.zip: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/wake.php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint must receive a request at least once before games in the old htdocs folder can be played. The launcher should send a request to it on startup.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Mounts &amp;lt;code&amp;gt;Server\htdocs&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;Games&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/games&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[filename]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP file into the virtual htdocs. The specified file must be located in the Games folder under the Flashpoint directory.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. If &amp;lt;code&amp;gt;wake.php&amp;lt;/code&amp;gt; has not run yet. It will run first.&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;/mnt/games/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; as a ZIP file (using fuse-zip)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
'''[https://drive.google.com/file/d/1pnbA9l4E0vi0EhmeO9Qi64ifvSbHShjF/view?usp=sharing Download Fresh Alpine Linux image (Updated: 2020-09-21)]'''&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://go.nul.sh/fpultimate -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
For Infinity use: https://go.nul.sh/fpinfinity&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3101</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3101"/>
		<updated>2020-09-21T13:29:59Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, so an FTP server runs on the host to share needed files.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/htdocs: (Initially unmounted) Contains the contents of the existing merged htdocs, for non-GameZIP games.&lt;br /&gt;
* /tmp/_&amp;lt;code&amp;gt;[game]&amp;lt;/code&amp;gt;.zip: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/wake.php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint must receive a request at least once before games in the old htdocs folder can be played. The launcher should send a request to it on startup.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Mounts &amp;lt;code&amp;gt;Server\htdocs&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;Games&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/games&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[filename]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP file into the virtual htdocs. The specified file must be located in the Games folder under the Flashpoint directory.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. If &amp;lt;code&amp;gt;wake.php&amp;lt;/code&amp;gt; has not run yet. It will run first.&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;/mnt/games/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; as a ZIP file (using fuse-zip)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
'''[https://drive.google.com/file/d/1pnbA9l4E0vi0EhmeO9Qi64ifvSbHShjF/view?usp=sharing Download Fresh Alpine Linux image (Updated: 2020-09-21)]'''&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://go.nul.sh/fpultimate -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
For Infinity use: https://go.nul.sh/fpinfinity&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3100</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3100"/>
		<updated>2020-09-21T12:17:56Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, so an FTP server runs on the host to share needed files.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/htdocs: (Initially unmounted) Contains the contents of the existing merged htdocs, for non-GameZIP games.&lt;br /&gt;
* /tmp/_&amp;lt;code&amp;gt;[game]&amp;lt;/code&amp;gt;.zip: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/wake.php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint must receive a request at least once before games in the old htdocs folder can be played. The launcher should send a request to it on startup.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Mounts &amp;lt;code&amp;gt;Server\htdocs&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;Games&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/games&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[filename]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP file into the virtual htdocs. The specified file must be located in the Games folder under the Flashpoint directory.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. If &amp;lt;code&amp;gt;wake.php&amp;lt;/code&amp;gt; has not run yet. It will run first.&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;/mnt/games/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; as a ZIP file (using fuse-zip)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
'''[https://drive.google.com/file/d/1pnbA9l4E0vi0EhmeO9Qi64ifvSbHShjF/view?usp=sharing Download Fresh Alpine Linux image (Updated: 2020-09-21)]'''&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Copy the PHP scripts/.htaccess that will be placed in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;Server\htdocs\base&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run Flashpoint Launcher (this will start the FTP server which allows access to the PHP scripts)&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://tinyurl.com/setfpup -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3099</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3099"/>
		<updated>2020-09-21T10:43:17Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification. [https://docs.google.com/document/d/1eo0k-HZ7asppGoGVJwZ9riyNtzJU-K0ljC1QrnnBQNk/edit?usp=sharing Read More]&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, so an FTP server runs on the host to share needed files.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/htdocs: (Initially unmounted) Contains the contents of the existing merged htdocs, for non-GameZIP games.&lt;br /&gt;
* /tmp/_&amp;lt;code&amp;gt;[game]&amp;lt;/code&amp;gt;.zip: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/wake.php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint must receive a request at least once before games in the old htdocs folder can be played. The launcher should send a request to it on startup.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Mounts &amp;lt;code&amp;gt;Server\htdocs&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;Games&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/games&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[filename]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP file into the virtual htdocs. The specified file must be located in the Games folder under the Flashpoint directory.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. If &amp;lt;code&amp;gt;wake.php&amp;lt;/code&amp;gt; has not run yet. It will run first.&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;/mnt/games/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; as a ZIP file (using fuse-zip)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Copy the PHP scripts/.htaccess that will be placed in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;Server\htdocs\base&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run Flashpoint Launcher (this will start the FTP server which allows access to the PHP scripts)&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://tinyurl.com/setfpup -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3098</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3098"/>
		<updated>2020-09-21T10:39:02Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification.&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, so an FTP server runs on the host to share needed files.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/htdocs: (Initially unmounted) Contains the contents of the existing merged htdocs, for non-GameZIP games.&lt;br /&gt;
* /tmp/_&amp;lt;code&amp;gt;[game]&amp;lt;/code&amp;gt;.zip: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/wake.php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint must receive a request at least once before games in the old htdocs folder can be played. The launcher should send a request to it on startup.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Mounts &amp;lt;code&amp;gt;Server\htdocs&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;Games&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/games&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[filename]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP file into the virtual htdocs. The specified file must be located in the Games folder under the Flashpoint directory.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. If &amp;lt;code&amp;gt;wake.php&amp;lt;/code&amp;gt; has not run yet. It will run first.&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;/mnt/games/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; as a ZIP file (using fuse-zip)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to return to the Alpine Linux shell.&lt;br /&gt;
&lt;br /&gt;
== Building the Alpine Linux image ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flashpoint contains a subset of the QEMU binaries to cut down of space. This means &amp;lt;code&amp;gt;qemu-img&amp;lt;/code&amp;gt; is missing.&lt;br /&gt;
&lt;br /&gt;
* Download the latest QEMU binaries [https://qemu.weilnetz.de/w64/]&lt;br /&gt;
* Extract them to the &amp;lt;code&amp;gt;Server&amp;lt;/code&amp;gt; folder in Flashpoint&lt;br /&gt;
&lt;br /&gt;
=== Installing Alpine Linux ===&lt;br /&gt;
&lt;br /&gt;
* Download the latest &amp;quot;Virtual&amp;quot; Alpine Linux release for x86 processors [https://www.alpinelinux.org/downloads/]&lt;br /&gt;
* Create a virtual disk image&lt;br /&gt;
 qemu-img create -f qcow2 alpine.qcow2 2G&lt;br /&gt;
&lt;br /&gt;
This will create a virtual disk image which will grow as needed up to a size of 2 GB.&lt;br /&gt;
&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user -hda alpine.qcow2 -boot d -cdrom alpine-virt-3.12.0-x86.iso&lt;br /&gt;
&lt;br /&gt;
This will boot the machine with maximum 512 MB of RAM and a bridged networking card.&lt;br /&gt;
&lt;br /&gt;
Go through the installation process. Once done, power off the machine using &amp;lt;code&amp;gt;poweroff&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to back up the qcow2 image at this point.&lt;br /&gt;
&lt;br /&gt;
=== Setting up the Flashpoint toolchain ===&lt;br /&gt;
&lt;br /&gt;
* Copy the PHP scripts/.htaccess that will be placed in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;Server\htdocs\base&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run Flashpoint Launcher (this will start the FTP server which allows access to the PHP scripts)&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the setup script (on the guest)&lt;br /&gt;
 cd /tmp&lt;br /&gt;
 wget https://tinyurl.com/setfpup -O setup&lt;br /&gt;
 chmod +x setup&lt;br /&gt;
 ./setup&lt;br /&gt;
* Clean up &amp;lt;code&amp;gt;/tmp&amp;lt;/code&amp;gt; and power off the machine (on the guest)&lt;br /&gt;
 rm -r /tmp/*&lt;br /&gt;
 poweroff&lt;br /&gt;
* Shrink your qcow2 image '''(Recommended)'''&lt;br /&gt;
 qemu-img convert -O qcow2 alpine.qcow2 alpine_setup.qcow2&lt;br /&gt;
 copy /Y alpine_setup.qcow2 alpine.qcow2&lt;br /&gt;
&lt;br /&gt;
=== Finalizing the image ===&lt;br /&gt;
&lt;br /&gt;
Finally, we need to set up our special save state to resume execution from.&lt;br /&gt;
* Boot the machine&lt;br /&gt;
 qemu-system-i386 -m 512 -net nic,model=e1000 -net user,hostfwd=tcp::22500-:80 -hda alpine.qcow2&lt;br /&gt;
* Run the following commands (on the guest)&lt;br /&gt;
 modprobe fuse&lt;br /&gt;
 unionfs /root/base /var/www/localhost/htdocs -o allow_other&lt;br /&gt;
 clear&lt;br /&gt;
 tail -f /var/log/apache2/access.log &amp;gt;/dev/ttyS0&lt;br /&gt;
* Press Ctrl+Alt+2. Type &amp;lt;code&amp;gt;savevm quick&amp;lt;/code&amp;gt; and press Enter. Wait, then quit QEMU.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;alpine.qcow2&amp;lt;/code&amp;gt; image is ready!&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3097</id>
		<title>QEMU GameZIP Server</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=QEMU_GameZIP_Server&amp;diff=3097"/>
		<updated>2020-09-21T10:06:58Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: Created page with &amp;quot;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs. This page aims to cover the details of the Flashpoint implementation.  == G...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server allows accessing zipped game contents, also known as GameZIPs, as well as merged htdocs.&lt;br /&gt;
This page aims to cover the details of the Flashpoint implementation.&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
* GameZIP: A zipped curation content folder, according to the GameZIP specification.&lt;br /&gt;
* merged htdocs: The root folder where web content is served from, contains matching file structure for hostnames used by games in Flashpoint.&lt;br /&gt;
* FUSE: [https://en.wikipedia.org/wiki/Filesystem_in_Userspace Filesystem in Userspace]&lt;br /&gt;
* union mount: A union mount is a mount which can appear to merge the contents of several directories, while keeping their physical content separate. [https://unionfs.filesystems.org/]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In the past, Flashpoint's server was an Apache httpd installation running on Windows.&lt;br /&gt;
The GameZIP implementation still uses Apache but it runs on Alpine Linux instead. This allows the use of FUSE file systems to achieve a simulated view of &amp;quot;merged htdocs&amp;quot; without the extraction of GameZIPs.&lt;br /&gt;
This instance of Alpine Linux is emulated under QEMU. QEMU was chosen because it requires no driver installation or special privileges and Alpine Linux because of its low file size and overhead.&lt;br /&gt;
The Linux guest cannot directly access files on the host file system, so an FTP server runs on the host to share needed files.&lt;br /&gt;
&lt;br /&gt;
=== Why emulate Linux? ===&lt;br /&gt;
&lt;br /&gt;
For our purposes, Apache is limited to a single web root and cannot serve files from ZIPs. Custom file systems require custom Windows drivers and are less mature or performant than FUSE.&lt;br /&gt;
In addition, the use of Linux allows for the use of the entire GNU/Linux toolkit which is very flexible. It also provides a security advantage, as it sandboxes potentially untrusted PHP scripts.&lt;br /&gt;
&lt;br /&gt;
== How does it work? ==&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU-FP.png]]&lt;br /&gt;
&lt;br /&gt;
The Apache installation has a single web root, found at &amp;lt;code&amp;gt;/var/www/localhost/htdocs&amp;lt;/code&amp;gt;.&lt;br /&gt;
This path is the target of a union mount, which merges the following paths:&lt;br /&gt;
* /root/base: Contains the PHP scripts required for mounting game ZIPs and the &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; that rewrites the HTTP Host header into a subfolder.&lt;br /&gt;
* /tmp/htdocs: (Initially unmounted) Contains the contents of the existing merged htdocs, for non-GameZIP games.&lt;br /&gt;
* /tmp/_&amp;lt;code&amp;gt;[game]&amp;lt;/code&amp;gt;.zip: (Initially unmounted) Contains the contents of a single GameZIP.&lt;br /&gt;
&lt;br /&gt;
When the emulated Alpine Linux instance starts, only &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; is part of the union.&lt;br /&gt;
&lt;br /&gt;
=== Mount API ===&lt;br /&gt;
&lt;br /&gt;
The scripts found in &amp;lt;code&amp;gt;/root/base&amp;lt;/code&amp;gt; make up the API used for controlling the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/wake.php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint must receive a request at least once before games in the old htdocs folder can be played. The launcher should send a request to it on startup.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. Mounts &amp;lt;code&amp;gt;Server\htdocs&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;Games&amp;lt;/code&amp;gt; from Flashpoint into &amp;lt;code&amp;gt;/mnt/games&amp;lt;/code&amp;gt; via FTP (using curlftpfs)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/mnt/htdocs&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/htdocs&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
* [GET] &amp;lt;code&amp;gt;http://127.0.0.1:22500/mount.php?file=[filename]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This endpoint allows mounting a game ZIP file into the virtual htdocs. The specified file must be located in the Games folder under the Flashpoint directory.&lt;br /&gt;
It has a few possible outcomes which it will print in plain text:&lt;br /&gt;
 “OK” (200): The file was mounted successfully.&lt;br /&gt;
 “ALREADY_MOUNTED” (200):&lt;br /&gt;
 The file was already previously mounted and remains available.&lt;br /&gt;
 “NO_SUCH_FILE” (400):&lt;br /&gt;
 The specified file was not found under the Games folder.&lt;br /&gt;
 “NO_CONTENT_FOLDER” (400):&lt;br /&gt;
 The specified file was not mounted because it did not contain a content folder.&lt;br /&gt;
 “BAD_ZIP” (400):&lt;br /&gt;
 The specified file was not mounted because it was not a valid ZIP file.&lt;br /&gt;
&lt;br /&gt;
This performs the following actions:&lt;br /&gt;
&lt;br /&gt;
1. If &amp;lt;code&amp;gt;wake.php&amp;lt;/code&amp;gt; has not run yet. It will run first.&lt;br /&gt;
&lt;br /&gt;
2. Mounts &amp;lt;code&amp;gt;/mnt/games/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; as a ZIP file (using fuse-zip)&lt;br /&gt;
&lt;br /&gt;
3. Mounts &amp;lt;code&amp;gt;/tmp/[filename]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; as a case-insensitive mirror (using fuzzyfs)&lt;br /&gt;
&lt;br /&gt;
4. Adds &amp;lt;code&amp;gt;/tmp/_[filename]&amp;lt;/code&amp;gt; to the union mount.&lt;br /&gt;
&lt;br /&gt;
=== Shell access ===&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;Data\services.json&amp;lt;/code&amp;gt; with a text editor. Remove &amp;lt;code&amp;gt;&amp;quot;-display&amp;quot;, &amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; from the arguments array in Apache Webserver and save.&lt;br /&gt;
The next time you run Flashpoint, you'll get a terminal to Alpine Linux. The root user has a blank password.&lt;br /&gt;
&lt;br /&gt;
[[File:QEMU.png|728px]]&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to terminate the tail command, this is used to pipe the contents of the Apache access log to the Flashpoint Launcher.&lt;br /&gt;
&lt;br /&gt;
To avoid the Linux boot time when starting the launcher, a QEMU savestate is used.&lt;br /&gt;
&lt;br /&gt;
* Press Ctrl+Alt+2 to access the QEMU console. Type &amp;lt;code&amp;gt;loadvm quick&amp;lt;/code&amp;gt; to reset the state of the machine.&lt;br /&gt;
* Press Ctrl+Alt+1 to go back to return to the Alpine Linux shell.&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=File:QEMU.png&amp;diff=3096</id>
		<title>File:QEMU.png</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=File:QEMU.png&amp;diff=3096"/>
		<updated>2020-09-21T09:59:01Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=File:QEMU-FP.png&amp;diff=3095</id>
		<title>File:QEMU-FP.png</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=File:QEMU-FP.png&amp;diff=3095"/>
		<updated>2020-09-21T09:20:12Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=YAML_Format&amp;diff=1363</id>
		<title>YAML Format</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=YAML_Format&amp;diff=1363"/>
		<updated>2019-09-04T13:43:09Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: Created page with &amp;quot;== Basic Principles ==  YAML is a very simple, human-readable text format that can be used to store data.  In YAML, data is stored as a map containing keys and values associat...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Principles ==&lt;br /&gt;
&lt;br /&gt;
YAML is a very simple, human-readable text format that can be used to store data.&lt;br /&gt;
&lt;br /&gt;
In YAML, data is stored as a map containing keys and values associated to those keys.&lt;br /&gt;
This map is in no particular order, so you may reorder it at will.&lt;br /&gt;
&lt;br /&gt;
 Title: Alien Hominid&lt;br /&gt;
 Series: &lt;br /&gt;
 Developer: The Behemoth&lt;br /&gt;
 Publisher:&lt;br /&gt;
 Play Mode: Single Player &lt;br /&gt;
 Status: Playable&lt;br /&gt;
 Extreme: No&lt;br /&gt;
 Genre: Shooter&lt;br /&gt;
 Source: Newgrounds.com&lt;br /&gt;
 Launch Command: http://uploads.ungrounded.net/59000/59593_alien_booya202c.swf&lt;br /&gt;
 Notes: &lt;br /&gt;
 Author Notes: Thanks for your work!&lt;br /&gt;
&lt;br /&gt;
=== Special Characters ===&lt;br /&gt;
&lt;br /&gt;
When using special characters, it is sometimes necessary to enclose the values in quotes or double quotes. Whichever you use is up to you.&lt;br /&gt;
&lt;br /&gt;
To simplify things, I suggest quoting all strings that contain special characters.&lt;br /&gt;
&lt;br /&gt;
'''Invalid:'''&lt;br /&gt;
&lt;br /&gt;
 Developer: @bluemaxima&lt;br /&gt;
            ^&lt;br /&gt;
'''Valid:'''&lt;br /&gt;
&lt;br /&gt;
 Developer: &amp;quot;@bluemaxima&amp;quot;&lt;br /&gt;
or&lt;br /&gt;
 Developer: '@bluemaxima'&lt;br /&gt;
&lt;br /&gt;
To ensure that your YAML is valid, you can copy and paste it to a site like [http://www.yamllint.com/ yamllint.com], it will tell you if its valid or if it's not, point you to where the issue is.&lt;br /&gt;
&lt;br /&gt;
=== Nested Keys ===&lt;br /&gt;
&lt;br /&gt;
Keys may also be inside other keys, this is denoted by the use of indentation. '''Do not use tabs for indentation. Always use spaces.'''&lt;br /&gt;
&lt;br /&gt;
The amount of spaces doesn't matter as long as all sub-keys use the same amount of spaces, though the general convention is to use two spaces.&lt;br /&gt;
&lt;br /&gt;
 Additional Applications:&lt;br /&gt;
   Extras: drop3&lt;br /&gt;
   Message: This message will pop up before the game runs.&lt;br /&gt;
   Play Hacked Version:&lt;br /&gt;
     Application Path: Games\flashplayer.exe&lt;br /&gt;
     Launch Command: http://www.irregulargames.com/drop3/drop3-hacked.swf&lt;br /&gt;
&lt;br /&gt;
=== Multiline Values ===&lt;br /&gt;
&lt;br /&gt;
Multiline values can be introduced by using a pipe &amp;quot;|&amp;quot; character. Content then starts in the next line and must be indented.&lt;br /&gt;
&lt;br /&gt;
These values do not need to be enclosed by quotes, regardless of any special characters.&lt;br /&gt;
&lt;br /&gt;
 Curation Notes: |&lt;br /&gt;
   This is a new example meta.txt.&lt;br /&gt;
   What do you think?&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
YAML files can include comments, these may appear anywhere in the file.&lt;br /&gt;
&lt;br /&gt;
 Title: Flashpoint&lt;br /&gt;
 # remember to quote values with special characters&lt;br /&gt;
 Developer: &amp;quot;@bluemaxima&amp;quot; # like this&lt;br /&gt;
&lt;br /&gt;
This means that if you want to include a number sign inside a value you must quote it.&lt;br /&gt;
&lt;br /&gt;
 Title: &amp;quot;#notacomment&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
A key can have multiple values, these are expressed by a dash &amp;quot;-&amp;quot; character in individual lines.&lt;br /&gt;
&lt;br /&gt;
 Languages:&lt;br /&gt;
 - en&lt;br /&gt;
 - es&lt;br /&gt;
 - fr&lt;br /&gt;
 - it&lt;br /&gt;
&lt;br /&gt;
Alternatively, you may also express them in a single line. To do so, enclose them in square brackets and separate them using commas.&lt;br /&gt;
&lt;br /&gt;
 Languages: [en, es, fr, it]&lt;br /&gt;
&lt;br /&gt;
=== Editor Choice ===&lt;br /&gt;
&lt;br /&gt;
It's not recommended to use a WYSIWYG editor like Word to edit YAML files.&lt;br /&gt;
&lt;br /&gt;
Instead, use something like Notepad++. You can also modify its settings so that pressing tab uses spaces [https://stackoverflow.com/a/7471232 like so].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Advanced Rules ==&lt;br /&gt;
&lt;br /&gt;
=== Quotes inside values ===&lt;br /&gt;
&lt;br /&gt;
In values enclosed by quotes &amp;quot;&amp;quot;, you may include quotes as part of the value itself by prepending them by a backslash &amp;quot;\&amp;quot; character.&lt;br /&gt;
&lt;br /&gt;
 Developer: &amp;quot;John \&amp;quot;Doe\&amp;quot; Douglas&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In values enclosed by single quotes &amp;lt;nowiki&amp;gt;''&amp;lt;/nowiki&amp;gt;, you may include single quotes as part of the value itself by doubling them up.&lt;br /&gt;
&lt;br /&gt;
 Developer: 'John &amp;lt;nowiki&amp;gt;''Doe''&amp;lt;/nowiki&amp;gt; Douglas'&lt;br /&gt;
&lt;br /&gt;
'''Cool trick'''&lt;br /&gt;
&lt;br /&gt;
You can also use the following to avoid having to escape values.&lt;br /&gt;
&lt;br /&gt;
 Curation Notes: &amp;gt;&lt;br /&gt;
   &amp;quot;Hello World&amp;quot; is a typical phrase used by programmers used in their first &amp;quot;program&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It's very similar to the multiline value syntax but using a greater-than symbol instead of a pipe.&lt;br /&gt;
&lt;br /&gt;
This syntax is called a &amp;quot;folded block&amp;quot;, this is because it allows you to cosmetically break up a value into multiple lines while keeping it in a single line once parsed.&lt;br /&gt;
&lt;br /&gt;
 folded_newlines: &amp;gt;&lt;br /&gt;
   this is really a&lt;br /&gt;
   single line of text&lt;br /&gt;
   despite appearances&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=HTML5_Curation&amp;diff=1263</id>
		<title>HTML5 Curation</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=HTML5_Curation&amp;diff=1263"/>
		<updated>2019-08-06T02:25:35Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: Placeholder&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In this guide I’ll explain how to curate HTML5 games. This will only cover games that don’t require a persistent server connection.&lt;br /&gt;
&lt;br /&gt;
== Recognizing an HTML5 game ==&lt;br /&gt;
&lt;br /&gt;
Without looking at a web page’s source, there’s no definitive way to tell if you’re dealing with an HTML5 game. You can however easily discard Flash by whether a lego brick-shaped plug-in icon is displayed to the left of the address bar. The same goes for any technologies that make use of browser plugins (e.g. Java).&lt;br /&gt;
&lt;br /&gt;
[[File:PluginIcon.PNG|plugin]]&lt;br /&gt;
&lt;br /&gt;
== Required software ==&lt;br /&gt;
&lt;br /&gt;
These will be required to perform the curation process:&lt;br /&gt;
&lt;br /&gt;
* [https://bluemaxima.org/flashpoint/downloads/ Flashpoint Core] (Optional, recommended)&lt;br /&gt;
* [https://eternallybored.org/misc/wget/ wget for Windows]&lt;br /&gt;
&lt;br /&gt;
The guide below will explain how to use them.&lt;br /&gt;
&lt;br /&gt;
== Curation ==&lt;br /&gt;
&lt;br /&gt;
In order to curate an HTML5 game, we first want to retrieve all the URLs required by the specific game we’re dealing with.&lt;br /&gt;
&lt;br /&gt;
There’s two ways to do so:&lt;br /&gt;
&lt;br /&gt;
* Using a web debugging proxy like Fiddler or Charles Proxy&lt;br /&gt;
* Using the browser’s console&lt;br /&gt;
&lt;br /&gt;
I personally prefer using Charles Proxy, I also use it for curating Flash games, which requests are not displayed in the browser’s console. I like its interface and it allows you to view the directory hierarchy of all HTTP requests.&lt;br /&gt;
&lt;br /&gt;
For the purposes of this guide I’m going to keep it simple and stick to Firefox’s console, which should be similar enough to that of Chrome. If you do opt for a debugging proxy it’s imperative to clear the browser’s cache EVERY time you attempt to capture the game’s requests.&lt;br /&gt;
&lt;br /&gt;
I’ll illustrate each step with an example of a real HTML5 game. I’m going to attempt to curate Google’s snake clone that you get by performing a search for “snake”.&lt;br /&gt;
&lt;br /&gt;
Here’s our prey:&lt;br /&gt;
&lt;br /&gt;
[[File:Snake.png|screenshot]]&lt;br /&gt;
&lt;br /&gt;
Let’s start off by opening the console, we can easily do this by pressing '''Ctrl+Shift+I''' or by right clicking anywhere in the page and then selecting “Inspect”. Then navigate to the “Network” tab.&lt;br /&gt;
&lt;br /&gt;
If any requests are already shown, click on the “Clear” icon to get a fresh start. While this tab is selected, our browser will record all requests made by the page and display them as a list.&lt;br /&gt;
&lt;br /&gt;
Refresh the page, this will cause it to make a bunch of requests to display the page. As the game loads, a bunch more requests will be made.&lt;br /&gt;
&lt;br /&gt;
Now, here’s where it gets tricky because most HTML5 games won’t request all of the files it needs at once but rather will request them sort of on-demand.&lt;br /&gt;
&lt;br /&gt;
Imagine a game that has multiple stages, and stage two uses a different music track, it may not request it until that stage starts. Depending on the game though, it is sometimes possible to retrieve a list of most if not all of the files it needs by exploring the contents of other files it requests.&lt;br /&gt;
&lt;br /&gt;
This could be an XML or JSON file that lists the music track to be used for each stage, for example. However, I won’t get into detail for now. This game does not require any of that.&lt;br /&gt;
&lt;br /&gt;
Play around with the game until no more requests are made or you feel satisfied. Then look for a button named “HAR”, it should be in the top right of the editor in Firefox, download icon in Chrome. Click it and select “Save everything as HAR”.&lt;br /&gt;
&lt;br /&gt;
This file contains the data of all the requests listed in the console. You can quickly extract all the requested URLs by opening the file in a text editor (i.e. notepad) and copy/pasting the contents in the left text box shown [https://jsfiddle.net/XXLuigiMario/pxcmew9t/show here].&lt;br /&gt;
&lt;br /&gt;
Copy the URLs from the right and save them in a new text file in its own dedicated folder.&lt;br /&gt;
&lt;br /&gt;
At this point, make sure you have a copy of Flashpoint for testing. Flashpoint Core is recommended but any version can be used.&lt;br /&gt;
&lt;br /&gt;
Next up, we’ll need to use a tool called wget. Chances are you have heard about it before, you can download it for Windows [https://eternallybored.org/misc/wget/ here].&lt;br /&gt;
&lt;br /&gt;
Save it in the same folder as the text file with the URLs, then open a command line window. To do so, simply press '''Win+R''', type “cmd” and then '''Enter'''.&lt;br /&gt;
&lt;br /&gt;
Type “cd”, without quotes, followed by the path to the folder where you saved your text file and '''Enter'''. Example: cd C:\Users\Foo\Game\&lt;br /&gt;
&lt;br /&gt;
Then enter “wget -x -i filename.txt” and let it do its thing. Once all files have been downloaded, copy the resulting folder(s) to the “htdocs” folder in your Flashpoint directory, you will find it under a folder named “Server”.&lt;br /&gt;
&lt;br /&gt;
Navigate into a folder named “FPSoftware” next to where you found “Server”, find an executable for a web browser named Basilisk in it and run it. Copy the base URL of the game into its address bar and press '''Enter'''.&lt;br /&gt;
&lt;br /&gt;
If the game works then you’re almost done! :)&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=File:PluginIcon.PNG&amp;diff=1262</id>
		<title>File:PluginIcon.PNG</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=File:PluginIcon.PNG&amp;diff=1262"/>
		<updated>2019-08-06T02:21:48Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=File:Snake.png&amp;diff=1261</id>
		<title>File:Snake.png</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=File:Snake.png&amp;diff=1261"/>
		<updated>2019-08-06T02:20:18Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=Instructions_for_Curating&amp;diff=1118</id>
		<title>Instructions for Curating</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=Instructions_for_Curating&amp;diff=1118"/>
		<updated>2019-06-17T07:38:24Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: Dirty Joe is not a decompiler, replaced by Luyten&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Guide ==&lt;br /&gt;
&lt;br /&gt;
* Download [https://drive.google.com/file/d/1qoQc32vQ7nnTmYMle1uCpluYenY61Biy/view Flashpoint Core 3], a lightweight developer version of Flashpoint&lt;br /&gt;
* Most games are tested within &amp;lt;code&amp;gt;Flashpoint Core X.X/Server/htdocs&amp;lt;/code&amp;gt;. X.X is the version number&lt;br /&gt;
* Make note of the direct URL to the game's main files you've extracted&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Important''', for most non-flash games, you need to save not only the game main file, but also the HTML code snippet in which the main file is embedded - place that in an index.html file, and keep reading &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* Within htdocs, make a folder with the website name &lt;br /&gt;
** i.e. &amp;lt;code&amp;gt;newgrounds.com&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;static.nickjr.com&amp;lt;/code&amp;gt;, etc&lt;br /&gt;
* Within that folder, begin mimicking the URL by building corresponding subdirectories.&lt;br /&gt;
** i.e. &amp;lt;code&amp;gt;newgrounds.com/alienhominid/59593_alien_booya202c.swf&amp;lt;/code&amp;gt; - you would make an &amp;lt;code&amp;gt;alienhominid&amp;lt;/code&amp;gt; subfolder, if your url has more, keep adding subfolders until it looks like your url&lt;br /&gt;
* Finally, place your game's main files in the last subfolder (along with an &amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt; if you've created one)&lt;br /&gt;
&lt;br /&gt;
'''Now that you have the code set up correctly in htdocs:'''&lt;br /&gt;
&lt;br /&gt;
* Open up Flashpoint Core and click on New Game on the bottom right corner &lt;br /&gt;
* Click on &amp;lt;u&amp;gt;Application Path&amp;lt;/u&amp;gt; and select the appropriate path for your extracted game &lt;br /&gt;
** i.e. flashplayer.exe for flash, startUnity.bat for Unity, etc. &lt;br /&gt;
* The &amp;lt;u&amp;gt;Launch command&amp;lt;/u&amp;gt; should be the exact URL to where you extracted the game&lt;br /&gt;
** '''However''', for most non-Flash games, you need to link it to the html in which the game is embedded&lt;br /&gt;
* If you want to edit these locations later, head to the Arcade tab and select the game (there will be a pencil image and a trash image next to the name) and click the pencil&lt;br /&gt;
* You should see a new game in the launcher list&lt;br /&gt;
* Run it &lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
&lt;br /&gt;
* Observe the Flashpoint redirector window and see if you're getting 404 errors - you can grab any missing assets or code by going to the indicated URL locations, downloading it and placing it correctly in the htdocs&lt;br /&gt;
* Hunt down other websites in which the game has been embedded or even originally hosted if any of the files end up being broken&lt;br /&gt;
* If you wish to decompile and look at the code, there are a few tools available. &lt;br /&gt;
Flash - [https://www.free-decompiler.com/flash/ JPEXS Flash Decompiler]  &lt;br /&gt;
&lt;br /&gt;
Java - [https://github.com/deathmarine/Luyten/releases/latest Luyten Java Decompiler]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once it works, follow the instructions on the [[Curation_Format]].&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
	<entry>
		<id>https://flashpointarchive.org/w/index.php?title=Lost_Games&amp;diff=529</id>
		<title>Lost Games</title>
		<link rel="alternate" type="text/html" href="https://flashpointarchive.org/w/index.php?title=Lost_Games&amp;diff=529"/>
		<updated>2018-07-19T00:00:59Z</updated>

		<summary type="html">&lt;p&gt;XXLuigiMario: Added Empires &amp;amp; Allies&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a list of games that we couldn't find on the internet and are lost forever.&lt;br /&gt;
&lt;br /&gt;
If you have any information or contact regarding these titles, please contact us in our discord.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;font-weight:bold;&amp;quot; | Game Name&lt;br /&gt;
! style=&amp;quot;font-weight:bold;&amp;quot; | Status&lt;br /&gt;
|-&lt;br /&gt;
| Mystery of Time and Space (MOTAS)&lt;br /&gt;
| Missing episodes 14-20&lt;br /&gt;
|-&lt;br /&gt;
| Shadow Rising&lt;br /&gt;
| Lots of missing assets&lt;br /&gt;
|-&lt;br /&gt;
| Empires &amp;amp; Allies (2011)&lt;br /&gt;
| Missing all assets, would also require server emulation&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>XXLuigiMario</name></author>
	</entry>
</feed>