mirror of
https://github.com/QuiteAFancyEmerald/Holy-Unblocker.git
synced 2025-05-13 03:50:02 -04:00
Massive Update
This commit is contained in:
parent
d2547cf7b2
commit
003b5da951
61 changed files with 1660 additions and 126179 deletions
|
@ -117,8 +117,8 @@ This is an example of DNS records involving Heroku. Self-hosting will require `A
|
||||||
<img src="https://cdn.discordapp.com/attachments/725506757291671663/756659513179766844/unknown.png" width="500" height="154"></img>
|
<img src="https://cdn.discordapp.com/attachments/725506757291671663/756659513179766844/unknown.png" width="500" height="154"></img>
|
||||||
|
|
||||||
- `a.deepsoil.ml` is being used for Node Unblocker.
|
- `a.deepsoil.ml` is being used for Node Unblocker.
|
||||||
- `c.deepsoil.ml` is being used for Powermouse.
|
- `p.deepsoil.ml` is being used for Powermouse.
|
||||||
- `cdn.deepsoil.ml` is being used for Via.
|
- `pd.deepsoil.ml` is being used for PyDodge B.
|
||||||
- `cdn.deepsoil.ml` is being used for a private Alloy host on the official sites.
|
- `cdn.deepsoil.ml` is being used for a private Alloy host on the official sites.
|
||||||
|
|
||||||
As stated previously, Holy Unblocker is hosted locally with Alloy.
|
As stated previously, Holy Unblocker is hosted locally with Alloy.
|
||||||
|
|
5
app.js
5
app.js
|
@ -1,3 +1,8 @@
|
||||||
|
/* -----------------------------------------------
|
||||||
|
/* Author : QuiteAFancyEmerald and YÖCTDÖNALD'S with help from MikeLime and SexyDuceDuce
|
||||||
|
/* MIT license: http://opensource.org/licenses/MIT
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
const
|
const
|
||||||
express = require('express'),
|
express = require('express'),
|
||||||
app = express(),
|
app = express(),
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* -----------------------------------------------
|
||||||
|
/* Author : Divide
|
||||||
|
/* MIT license: http://opensource.org/licenses/MIT
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
mime = require('mime-types'),
|
mime = require('mime-types'),
|
||||||
|
|
13
package-lock.json
generated
13
package-lock.json
generated
|
@ -13,6 +13,14 @@
|
||||||
"negotiator": "0.6.2"
|
"negotiator": "0.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"alloyproxy": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/alloyproxy/-/alloyproxy-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-2MnpZduvj7YwOIsR3r07r4YXO12FpyN7xcZpWVTHtYC5xofXLgqsn9QZLpl4FgaePKqJkT9lT6CMIUFKF0IR4A==",
|
||||||
|
"requires": {
|
||||||
|
"ws": "^7.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"array-flatten": {
|
"array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
|
@ -434,6 +442,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||||
},
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "7.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz",
|
||||||
|
"integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ=="
|
||||||
|
},
|
||||||
"xss": {
|
"xss": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.8.tgz",
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
"author": "Titanium Network",
|
"author": "Titanium Network",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"alloyproxy": "^1.0.0",
|
||||||
"cookie-parser": "^1.4.5",
|
"cookie-parser": "^1.4.5",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-session": "^1.17.1",
|
"express-session": "^1.17.1",
|
||||||
|
|
119319
public/assets/js/Run3.js
119319
public/assets/js/Run3.js
File diff suppressed because one or more lines are too long
|
@ -1,10 +0,0 @@
|
||||||
// configuration
|
|
||||||
var opts = {
|
|
||||||
romReaders: [
|
|
||||||
new GameboyJS.RomFileReader(),
|
|
||||||
new GameboyJS.RomDropFileReader(document.getElementById('dropzone'))
|
|
||||||
]
|
|
||||||
};
|
|
||||||
var g = new GameboyJS.Gameboy(document.getElementById('canvas'), opts);
|
|
||||||
g.setSoundEnabled(document.getElementById('sound-enable').checked);
|
|
||||||
g.setScreenZoom(document.getElementById('screen-zoom').value);
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* -----------------------------------------------
|
||||||
|
/* Authors: OlyB
|
||||||
|
/* MIT license: http://opensource.org/licenses/MIT
|
||||||
|
/* GFiles - Edited
|
||||||
|
/* ----------------------------------------------- */
|
||||||
function gsearch() {
|
function gsearch() {
|
||||||
var e, t, n, a;
|
var e, t, n, a;
|
||||||
for (e = document.getElementById("gsearchbar").value.toUpperCase(), t = document.getElementById("glist"), a = 0; a < t.querySelectorAll("a[href]").length; a++)(n = t.getElementsByTagName("a")[a]).innerHTML.toUpperCase().indexOf(e) > -1 ? n.style.display = "block" : n.style.display = "none"
|
for (e = document.getElementById("gsearchbar").value.toUpperCase(), t = document.getElementById("glist"), a = 0; a < t.querySelectorAll("a[href]").length; a++)(n = t.getElementsByTagName("a")[a]).innerHTML.toUpperCase().indexOf(e) > -1 ? n.style.display = "block" : n.style.display = "none"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,10 @@
|
||||||
|
/* -----------------------------------------------
|
||||||
|
/* Authors: YÖCTDÖNALD'S and OlyB
|
||||||
|
/* MIT license: http://opensource.org/licenses/MIT
|
||||||
|
/* Tab Cloak - Script
|
||||||
|
/* v1.5.0
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
/*Title & Icon Presets*/
|
/*Title & Icon Presets*/
|
||||||
let titles = icons = [];
|
let titles = icons = [];
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* -----------------------------------------------
|
||||||
|
/* Author: Divide
|
||||||
|
/* MIT license: http://opensource.org/licenses/MIT
|
||||||
|
/* Cloak
|
||||||
|
/* ----------------------------------------------- */
|
||||||
document.onkeydown = (function(e) {
|
document.onkeydown = (function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.which == 17) cip = true;
|
if (e.which == 17) cip = true;
|
||||||
|
|
|
@ -1,220 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
|
||||||
<!-- Important: Use ​ to mess with keywords. -->
|
|
||||||
<title>H​oly Unb​loc​ke​r</title>
|
|
||||||
<meta name="description" content="G​et p​ast in​te​r​net ce​n​s​or​sh​ip tod​a​y!
|
|
||||||
|
|
||||||
:D">
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/i.png">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat+Alternates">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Titillium+Web:400,600,700">
|
|
||||||
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/fonts/ionicons.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
|
||||||
<!-- Assets -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
|
||||||
<script src="assets/js/header.js"></script>
|
|
||||||
<script async src="https://arc.io/widget.js#2BzvQ1em"></script>
|
|
||||||
<!--<script src="assets/js/im-runtime.js"></script>-->
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="particles-js">
|
|
||||||
<script>
|
|
||||||
/* particlesJS.load(@dom-id, @path-json, @callback (optional)); */
|
|
||||||
particlesJS.load('particles-js', 'particles.json', function() {
|
|
||||||
console.log('particlesjs loaded.......');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<div>
|
|
||||||
<h1 id="holy-unblocker">Documentation</h1>
|
|
||||||
<p>A website that can be used to bypass web filters; both extension and firewall. This is the official documentation for Holy Unblocker, a rather fancy website with some cool dynamic backgrounds while also focusing with detail put into the design and mechanics overall. Also has cool features like custom Tab Cloaks and with more to come. Works on a large number of sites including YouTube (Full Quality Support), Discord, CoolMathGames and more! Be sure to check the various branches as I update Holy Unblocker often with open access to yet to be released versions.</p>
|
|
||||||
<p>Official Site: <a href="https://www.holyubofficial.net">https://www.holyubofficial.net</a></p>
|
|
||||||
<p>Be sure to join Titanium Network's Discord for more official site links: <a href="https://discord.com/invite/tgT48PH">https://discord.com/invite/tgT48PH</a></p>
|
|
||||||
<p><a href="https://heroku.com/deploy?template=https://github.com/QuiteAFancyEmerald/HolyUnblockerPublic" title="Deploy to Heroku"><img alt="Deploy to Heroku" src="https://raw.githubusercontent.com/QuiteAFancyEmerald/HolyUnblockerPublic/master/public/assets/img/heroku.svg?raw" width="140" height="30"><img></a>
|
|
||||||
|
|
||||||
<a href="https://azuredeploy.net/" title="Deploy to Azure"><img alt="Deploy to Azure" src="https://raw.githubusercontent.com/QuiteAFancyEmerald/HolyUnblockerPublic/master/public/assets/img/azure.svg?raw" width="140" height="30"><img></a>
|
|
||||||
|
|
||||||
<a href="https://repl.it/github/QuiteAFancyEmerald/HolyUnblockerPublic" title="Run on Repl.it"><img alt="Run on Repl.it" src="https://raw.githubusercontent.com/QuiteAFancyEmerald/HolyUnblockerPublic/master/public/assets/img/replit.svg?raw" width="140" height="30"><img></a>
|
|
||||||
|
|
||||||
<a href="https://glitch.com/edit/#!/import/github/QuiteAFancyEmerald/HolyUnblockerPublic" title="Remix on Glitch"><img alt="Remix on glitch" src="https://raw.githubusercontent.com/QuiteAFancyEmerald/HolyUnblockerPublic/master/public/assets/img/glitch.svg?raw" width="140" height="30"><img></a></p>
|
|
||||||
<h2 id="table-of-contents-">Table of contents:</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#how-to-install">Setup</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#structure">Structure</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#structure-information">Structure Information</a></li>
|
|
||||||
<li><a href="#details-of-public">Static Files</a></li>
|
|
||||||
<li><a href="#scripts-located-in-expr">Proxy Scripts</a></li>
|
|
||||||
<li><a href="#details-of-authjs">Cookie Auth</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#future-additions">Future Additions</a></li>
|
|
||||||
<li><a href="#vauge-explanation-for-beginners-with-external-and-hosting">Beginner's Explanation</a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#list-of-some-good-hosting-options">Hosting Providers</a></li>
|
|
||||||
<li><a href="#heroku-steps">Heroku Setup</a></li>
|
|
||||||
<li><a href="#freenomdomain-steps">Domain Setup</a></li>
|
|
||||||
<li><a href="#cloudflare-steps">Cloudflare Setup</a></li>
|
|
||||||
<li><a href="#workspace-configurations">Workspace Configurations</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="#more-information">More Information</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h2 id="how-to-setup">How to Setup</h2>
|
|
||||||
<p>Either use the button above to deploy to Heroku or do the below:</p>
|
|
||||||
<pre><code>git <span class="hljs-keyword">clone</span> <span class="hljs-title">https</span>://github.com/QuiteAFancyEmerald/HolyUnblockerPublic.git
|
|
||||||
|
|
||||||
cd HolyUnblockerPublic
|
|
||||||
|
|
||||||
npm install
|
|
||||||
|
|
||||||
npm <span class="hljs-literal">start</span>
|
|
||||||
</code></pre>
|
|
||||||
<p>The default place for the proxy when its started is <code>http://localhost:8081</code> but you can change it if needed in config.json</p>
|
|
||||||
<p>This website has been hosted locally on Alloy Proxy. More more information go to the Alloy Proxy repo below.</p>
|
|
||||||
<h2 id="structure">Structure</h2>
|
|
||||||
<ul>
|
|
||||||
<li><code>index.html</code> : The official homepage of the site.</li>
|
|
||||||
<li><code>surf.html</code> : Surf Freely page, page offers to be redirected to either Alloy or Node.</li>
|
|
||||||
<li><code>alloy.html</code> : Alloy Proxy page, configured as recommended with Alloy Proxy.</li>
|
|
||||||
<li><code>node.html</code> : Links to a subdomain for Node Unblocker. I left it in just in case you would like to setup the site differently.</li>
|
|
||||||
<li><code>pmprox.html</code> : Links to a subdomain for Powermouse. I left it in just in case you would like to setup the site differently.</li>
|
|
||||||
<li><code>gtools.html</code> : Games page, help from @BinBashBanana and @kinglalu.</li>
|
|
||||||
<li><code>info.html</code> : WIP Documentation.</li>
|
|
||||||
<li><code>discordhub.html</code> : Hub for the discord proxy and its links.</li>
|
|
||||||
<li><code>discordprox.html</code> : Links to a discord proxied through Alloy.</li>
|
|
||||||
<li><code>pydodge.html</code> : Links to a subdomain with PyDodge B. Created by OlyB from a modified Via Proxy.</li>
|
|
||||||
<li><code>flash.html</code> : Games page for flash games, credits given to @BinBashBanana and Titanium Network for its assets.</li>
|
|
||||||
<li><code>icons.html</code> : Information regarding Settings Menu page. Added this in for standard users.</li>
|
|
||||||
<li><code>terms.html</code> : Terms of Services, AUP and Privacy Policy page.</li>
|
|
||||||
<li><code>gba.html</code> : Locally hosted Gameboy Emulator.</li>
|
|
||||||
<li><code>krunker.html</code> : An iframe version of Krunker with keyword changes. Can be removed if not needed.</li>
|
|
||||||
<li><code>youtube.html</code> : An proxied version of Youtube running off of the locally hosted Alloy Proxy.</li>
|
|
||||||
<li><code>ythub.html</code> : Page linking proxied Youtube.</li>
|
|
||||||
<li><code>ytmobile.html</code> : Page linking to a proxied YouTube for mobile users.</li>
|
|
||||||
<li><code>chatbox.html</code> : Links to an externally hosted Chatbox.</li>
|
|
||||||
<li><code>bookmarklets.html</code> : Page for Bookmarklets.<h3 id="structure-information">Structure Information</h3>
|
|
||||||
</li>
|
|
||||||
<li><code>/public/</code> : The physical site base of Holy Unblocker goes here. Do not delete or modify <code>/utils</code> as its needed for Alloy.</li>
|
|
||||||
</ul>
|
|
||||||
<h4 id="details-of-public-">Details of <code>/public</code></h4>
|
|
||||||
<ul>
|
|
||||||
<li><code>/pages/</code> is used for important pages for the site.</li>
|
|
||||||
<li><code>/expr/</code> is used for important proxy scripts.</li>
|
|
||||||
<li><code>/archive/</code> and <code>/css</code> is used for game related assets and pages.</li>
|
|
||||||
<li><code>/assets/</code> is used for various assets for CSS, JS and Bootstrap.</li>
|
|
||||||
<li><code>/vibeOS/</code> is used for vibeOS, an in-browser OS enviroment.</li>
|
|
||||||
</ul>
|
|
||||||
<h4 id="scripts-located-in-expr-">Scripts located in <code>/expr</code></h4>
|
|
||||||
<ul>
|
|
||||||
<li><code>[Proxy Initial]bp.js</code> is used for future implementation of Cookie Auth and navigation to external proxies. Must be located in the
|
|
||||||
|
|
||||||
<body> tag.</li>
|
|
||||||
<li><code>[Proxy Initial]load.js</code> is used for initializing the bp script(s). Must be located in the <code><head></code> tag.</li>
|
|
||||||
<li><code>d.html</code> is used for a locally running Discord proxy along with <code>dbp.js</code></li>
|
|
||||||
</ul>
|
|
||||||
<h4 id="details-of-auth-js-">Details of <code>auth.js</code></h4>
|
|
||||||
<ul>
|
|
||||||
<li>Will be used for the implementation of Cookie Authorization</li>
|
|
||||||
</ul>
|
|
||||||
<h2 id="future-additions">Future Additions</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Cookie Authorization</li>
|
|
||||||
<li>Filters</li>
|
|
||||||
</ul>
|
|
||||||
<h2 id="vauge-explanation-for-beginners-with-external-and-hosting">Vauge Explanation for Beginners With External Proxies and Hosting</h2>
|
|
||||||
<p>You will first want to host your proxies locally or externally. </p>
|
|
||||||
<h4 id="list-of-some-good-hosting-options">List of some good hosting options:</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://heroku.com">Heroku</a> (Free)</li>
|
|
||||||
<li><a href="https://nodeclusters.com">NodeClusters</a> (Paid)</li>
|
|
||||||
<li><a href="https://glitch.com">Glitch</a> (Free)</li>
|
|
||||||
<li><a href="https://repl.it">Repl.it</a> (Free)</li>
|
|
||||||
<li><a href="https://azure.microsoft.com/en-us/">Azure</a> (Free and Paid)</li>
|
|
||||||
</ul>
|
|
||||||
<p>Out of the list of hosting providers Heroku and NodeClusters rank first as a preference. You may also self-host. Currently at this time Azure is used to host the official Holy Unblocker sites.</p>
|
|
||||||
<p>After you have selected a decent VPS, use Cloudflare for the DNS records for both the site and the subdomains for the proxies.</p>
|
|
||||||
<p>This is an example of DNS records involving Heroku. Self-hosting will require <code>A records</code> preferably.
|
|
||||||
<img src="https://cdn.discordapp.com/attachments/725506757291671663/756659513179766844/unknown.png" width="500" height="154"></img></p>
|
|
||||||
<ul>
|
|
||||||
<li><code>a.deepsoil.ml</code> is being used for Node Unblocker.</li>
|
|
||||||
<li><code>p.deepsoil.ml</code> is being used for Powermouse.</li>
|
|
||||||
<li><code>pd.deepsoil.ml</code> is being used for PyDodge B.</li>
|
|
||||||
<li><code>cdn.deepsoil.ml</code> is being used for a private Alloy host on the official sites.</li>
|
|
||||||
</ul>
|
|
||||||
<p>As stated previously, Holy Unblocker is hosted locally with Alloy.</p>
|
|
||||||
<h4 id="heroku-steps">Heroku Steps</h4>
|
|
||||||
<p><strong>So use Heroku to host. I personally favor it as a free choice.</strong> </p>
|
|
||||||
<ul>
|
|
||||||
<li>First obtain a card; (Prepaid, Debit, and Credit Cards work). You need this to add custom domains to your Heroku instance.</li>
|
|
||||||
</ul>
|
|
||||||
<p>Make sure you connect your Heroku app to your GitHub and enable automatic deploys. Will make things easier. :) </p>
|
|
||||||
<h4 id="freenom-domain-steps">Freenom/Domain Steps</h4>
|
|
||||||
<p>For beginners, Freenom is a good provider for obtaining domains for free. However the catch is that you can only use properly "Freenom" domains for free being .cf, .ml, .gq, ga and .tk. However these can be blocked rather easily.</p>
|
|
||||||
<ul>
|
|
||||||
<li>Get some Freenom domains then add them to your Heroku instance (Personal > [App Name] > Settings > Domains)
|
|
||||||
Add a domain for both <code>www.youdomainhere.cf</code> and <code>yourdomainhere.cf</code> with .cf being interchangeable with other Freedom domain names.</li>
|
|
||||||
<li>If you prefer to obtain premium domains (TLDs) then use <a href="https://porkbun.com">Porkbun</a>, which offers domains for amazing prices. Literally a <code>.net</code> domain normally costs around $10. On Porkbun for the first year it costs $3 so its definitely a deal.</li>
|
|
||||||
</ul>
|
|
||||||
<h4 id="cloudflare-steps">Cloudflare Steps</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Use Cloudflare (make an account), add your site (Freenom Domain or Domain) and then add your various DNS targets to Cloudflare. Make sure you add Cloudflare's Nameservers which will be specified more when you are adding your site. </li>
|
|
||||||
</ul>
|
|
||||||
<p>Make sure they are CNAME although A records also work and try to follow this structure:</p>
|
|
||||||
<p><strong>Type | Name | Target</strong></p>
|
|
||||||
<p><code>CNAME | www | yourherokutargethere.herokudns.com</code>
|
|
||||||
<code>CNAME | @ | yourherokudnstargethere.herokudns.com</code></p>
|
|
||||||
<p><strong>Below are if you want external proxies also with your site:</strong></p>
|
|
||||||
<p><code>CNAME | a | yournodeinstance.herokudns.com</code>
|
|
||||||
<code>CNAME | pd | yourpydodgebinstancehere.herokudns.com</code>
|
|
||||||
<code>CNAME | p | yourpowermouseinstancehere.herokudns.com</code></p>
|
|
||||||
<p>Make sure HTTPS is forced and have SSL set to Flexible for Heroku. Otherwise you can have SSL set to Full.</p>
|
|
||||||
<h4 id="workspace-configurations">Workspace Configurations</h4>
|
|
||||||
<p>Preferably if you have your own device use Visual Studio Code. Pretty much the best option you can get but obviously this is an opinion. Also make sure you have <a href="https://nodejs.org/">Node.JS</a> installed on your machine.</p>
|
|
||||||
<p>Not going to go too in depth with this part but first fork this repository. The clone it locally through a Terminal of some sort depending on what OS you are on. Make sure you navigate to the folder you want to set this up in.</p>
|
|
||||||
<pre><code>git <span class="hljs-keyword">clone</span> <span class="hljs-title">https</span>://github.com/QuiteAFancyEmerald/HolyUnblockerPublic.git
|
|
||||||
|
|
||||||
cd HolyUnblockerPublic
|
|
||||||
|
|
||||||
npm install
|
|
||||||
</code></pre>
|
|
||||||
<p>Now simply add the folder you cloned this repo in in VSC. Then run <code>npm install</code>. I recommend that if you are releasing this publically on GitHub that you add a <code>.gitignore</code> in your root directory with the following exclusions:</p>
|
|
||||||
<p><code>node_modules</code></p>
|
|
||||||
<p>Now you have your following workspace environment setup. To deploy the following workspace you just created you will need to look up depending on your hosting provider.</p>
|
|
||||||
<p>For an online IDE that you can use on your school computer and/or chromebook use GitPod. Basically the equivalent of Visual Studio Code but with in-browser support.</p>
|
|
||||||
<ul>
|
|
||||||
<li>Make an account: <code>https://gitpod.io/</code></li>
|
|
||||||
<li>Fork this repo and enter in this URL to setup your workspace: <code>https://gitpod.io#https://github.com/YourNameHere/HolyUnblockerPublic/</code></li>
|
|
||||||
</ul>
|
|
||||||
<p>Use the same steps above by running <code>npm install</code> in your repository and adding a <code>.gitignore</code> in your root directory specifying to exclude <code>node_modules</code>.</p>
|
|
||||||
<h2 id="more-information">More Information</h2>
|
|
||||||
<p>This project uses Alloy Proxy, Node Unblocker, Powermouse and PyDodge which are linked below. Credits also given to Titanium Network and all it's developers as this project would not be possible without them. View the official website for more detail. :)</p>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/titaniumnetwork-dev/">https://github.com/titaniumnetwork-dev/</a></li>
|
|
||||||
<li><a href="https://github.com/titaniumnetwork-dev/alloyproxy">https://github.com/titaniumnetwork-dev/alloyproxy</a></li>
|
|
||||||
<li><a href="https://github.com/nfriedly/node-unblocker">https://github.com/nfriedly/node-unblocker</a></li>
|
|
||||||
<li><a href="https://github.com/vibedivide/powermouse">https://github.com/vibedivide/powermouse</a></li>
|
|
||||||
<li><a href="https://github.com/BinBashBanana/PyDodge">https://github.com/BinBashBanana/PyDodge</a></li>
|
|
||||||
<li><a href="https://github.com/juchi/gameboy.js">https://github.com/juchi/gameboy.js</a></li>
|
|
||||||
<li><a href="https://nodeclusters.com">https://nodeclusters.com</a></li>
|
|
||||||
<li><a href="https://titaniumnetwork.org/">https://titaniumnetwork.org/</a></li>
|
|
||||||
<li><a href="https://github.com/vibedivide/vibeOS">https://github.com/vibedivide/vibeOS</a></li>
|
|
||||||
</ul>
|
|
||||||
<p>Thanks.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
<html>
|
|
|
@ -1,8 +0,0 @@
|
||||||
window.onload = function() {
|
|
||||||
var frame = document.getElementById("frame");
|
|
||||||
var det = document.domain;
|
|
||||||
var domain = det.replace('www.', '').split(/[/?#]/)[0];
|
|
||||||
frame.src = "https://c." + domain + "/app";
|
|
||||||
document.cookie = 'oldsmobile=badcar; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
|
||||||
return false;
|
|
||||||
};
|
|
|
@ -1,16 +0,0 @@
|
||||||
window.onload = function() {
|
|
||||||
var url = `https://discord.com/login`;
|
|
||||||
var det = document.domain;
|
|
||||||
var domain = det.replace('www.', '').split(/[/?#]/)[0];
|
|
||||||
const origin = btoa(url)
|
|
||||||
window.location.href = "https://" + domain + "/fetch/utils/?url=" + origin;
|
|
||||||
document.cookie = '__alloy_cookie_auth=yes; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cookie Auth
|
|
||||||
var host = location.hostname.split('.');
|
|
||||||
var auth = location.hostname;
|
|
||||||
if (host.length == 3) {
|
|
||||||
auth = `${host[1]}.${host[2]}`;
|
|
||||||
}
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* -----------------------------------------------
|
||||||
|
/* MIT license: http://opensource.org/licenses/MIT
|
||||||
|
/* How to use? : Check the documentation. Button ID attributes are used for the script below.
|
||||||
|
/* v2.0.0
|
||||||
|
/* ----------------------------------------------- */
|
||||||
$ = e => document.getElementById(e) || [];
|
$ = e => document.getElementById(e) || [];
|
||||||
|
|
||||||
//AL
|
//AL
|
||||||
|
@ -128,15 +133,6 @@ $('ytbp').onclick = function() {
|
||||||
document.cookie = 'oldsmobile=badcar; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
document.cookie = 'oldsmobile=badcar; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
$('chat').onclick = function() {
|
|
||||||
var frame = document.getElementById("frame");
|
|
||||||
var det = document.domain;
|
|
||||||
var domain = det.replace('www.', '').split(/[/?#]/)[0];
|
|
||||||
frame.src = "https://c." + domain + "/app";
|
|
||||||
frame.style['visibility'] = "visible";
|
|
||||||
document.cookie = 'oldsmobile=badcar; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
//D
|
//D
|
||||||
$('dbtn').onclick = function() {
|
$('dbtn').onclick = function() {
|
||||||
var frame = document.getElementById("frame");
|
var frame = document.getElementById("frame");
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
window.onload = function() {
|
|
||||||
// similar behavior as an HTTP redirect
|
|
||||||
var yt = `https://youtube.com`;
|
|
||||||
var det = document.domain;
|
|
||||||
var domain = det.replace('www.', '').split(/[/?#]/)[0];
|
|
||||||
const origin = btoa(yt);
|
|
||||||
window.location.replace("https://" + domain + "/fetch/utils/?url=" + origin);
|
|
||||||
document.cookie = '__alloy_cookie_auth=yes; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
|
||||||
}
|
|
||||||
// Cookie Auth
|
|
||||||
var host = location.hostname.split('.');
|
|
||||||
var auth = location.hostname;
|
|
||||||
if (host.length == 3) {
|
|
||||||
auth = `${host[1]}.${host[2]}`;
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
window.onload = function() {
|
|
||||||
// similar behavior as an HTTP redirect
|
|
||||||
var yt = `https://m.youtube.com`;
|
|
||||||
var det = document.domain;
|
|
||||||
var domain = det.replace('www.', '').split(/[/?#]/)[0];
|
|
||||||
const origin = btoa(yt);
|
|
||||||
window.location.replace("https://" + domain + "/fetch/utils/?url=" + origin);
|
|
||||||
document.cookie = '__alloy_cookie_auth=yes; expires=' + (Date.now() + 259200) + '; SameSite=Lax; domain=.' + auth + '; path=/; Secure;';
|
|
||||||
}
|
|
||||||
// Cookie Auth
|
|
||||||
var host = location.hostname.split('.');
|
|
||||||
var auth = location.hostname;
|
|
||||||
if (host.length == 3) {
|
|
||||||
auth = `${host[1]}.${host[2]}`;
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -17,7 +17,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -26,13 +26,12 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<!-- Important: Use <wbr> to mess with keywords. -->
|
<!-- Important: Use <wbr> to mess with keywords. -->
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px; z-index: 1;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px; z-index: 1;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -42,8 +41,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -158,7 +156,6 @@
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="assets/js/bs-init.js "></script>
|
<script src="assets/js/bs-init.js "></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,13 +27,12 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<!-- Important: Use <wbr> to mess with keywords. -->
|
<!-- Important: Use <wbr> to mess with keywords. -->
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -43,8 +42,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -103,13 +101,12 @@
|
||||||
<h1 class="text-center d-md-flex flex-grow-1 justify-content-md-center align-items-md-center" style="color: rgb(242,245,248);font-size: 46px;font-weight: normal;font-family: 'Montserrat Alternates', sans-serif;margin: 7px;padding: 34px;width: 100%;filter: blur(0px);height: 100%;">Credits<br></h1>
|
<h1 class="text-center d-md-flex flex-grow-1 justify-content-md-center align-items-md-center" style="color: rgb(242,245,248);font-size: 46px;font-weight: normal;font-family: 'Montserrat Alternates', sans-serif;margin: 7px;padding: 34px;width: 100%;filter: blur(0px);height: 100%;">Credits<br></h1>
|
||||||
<p><br> Quite A Fa​ncy Em​erald (Crea​tor and Ow​ner, Disco​rd: Quite A Fan​cy Emer​ald#0001)<br><br><strong>−−</strong><br>Contributors:<br>− Kin​glalu (Gam​es Page,
|
<p><br> Quite A Fa​ncy Em​erald (Crea​tor and Ow​ner, Disco​rd: Quite A Fan​cy Emer​ald#0001)<br><br><strong>−−</strong><br>Contributors:<br>− Kin​glalu (Gam​es Page,
|
||||||
Developer)
|
Developer)
|
||||||
<br><strong>− O​lyB (Tab Cl​oak, Web Developer)</strong><br><strong>− YOCTDON​ALD'S (Obfusc​ation God, T​N Bugh​unter)</strong><br><strong>− SexyDuceDuce (Pr​oxy and Web Dev​eloper)</strong><br><strong>−−</strong><br>Notable
|
<br><strong>− O​lyB (Tab Cl​oak, Web Developer)</strong><br><strong>− YOCTDON​ALD'S (Obfusc​ation God, T​N Bugh​unter)</strong><br><strong>− SexyDuceDuce (Pr​oxy and Web Dev​eloper)</strong><br><strong>−−</strong><br>Notable Mentions:
|
||||||
Mentions:
|
|
||||||
<br>− LQ16 (Creator of TN, Retired)</strong><br>−Shirt (Owner of TN)<br>− Mik<wbr>eLime (<strong>Co-Owner of Tit<wbr>anium<wbr>Ne<wbr>twork & Mass Pr<wbr>o<wbr>xy Site Maker, Web Deve​loper, and Software Developer</strong>)
|
<br>− LQ16 (Creator of TN, Retired)</strong><br>−Shirt (Owner of TN)<br>− Mik<wbr>eLime (<strong>Co-Owner of Tit<wbr>anium<wbr>Ne<wbr>twork & Mass Pr<wbr>o<wbr>xy Site Maker, Web Deve​loper, and Software Developer</strong>)
|
||||||
:D
|
:D
|
||||||
<br>− Sou​p (Cat La​dy) hehe<br>
|
<br>− Sou​p (Cat La​dy) hehe<br>
|
||||||
<br><strong>− Na<wbr>vvy</strong><br><strong>- Divi​de (Chatb​ox, Pro​xy/W​eb Deve​loper)<br><strong>− B<wbr>3A<wbr>TDR<wbr>O<wbr>P3R</strong><br>− Nautica<br><strong><br><strong>−−</strong><br>And
|
<br><strong>− Na<wbr>vvy</strong><br><strong>- Divi​de (Chatb​ox, Pro​xy/W​eb Deve​loper)<br><strong>− B<wbr>3A<wbr>TDR<wbr>O<wbr>P3R</strong><br>− Nautica<br><strong><br><strong>−−</strong><br>And
|
||||||
everyone else on TN and to the various testers. :D<br><br>And of course a certain Michael (irl friend)<br><br></p>
|
everyone else on TN and to the various testers. :D<br><br>And of course a certain Michael (irl friend)<br><br></p>div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -156,7 +153,6 @@
|
||||||
<script src="assets/js/links.js"></script>
|
<script src="assets/js/links.js"></script>
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -28,13 +28,12 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<!-- Important: Use <wbr> to mess with keywords. -->
|
<!-- Important: Use <wbr> to mess with keywords. -->
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -44,8 +43,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -279,7 +277,6 @@
|
||||||
<script src="assets/js/links.js"></script>
|
<script src="assets/js/links.js"></script>
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -17,7 +17,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -28,11 +28,10 @@
|
||||||
<!--Games Old CSS -->
|
<!--Games Old CSS -->
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -56,8 +55,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -470,7 +468,6 @@
|
||||||
<script src="assets/js/links.js"></script>
|
<script src="assets/js/links.js"></script>
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -28,13 +28,11 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<!--New-->
|
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -44,8 +42,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -167,7 +164,6 @@
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="assets/js/bs-init.js"></script>
|
<script src="assets/js/bs-init.js"></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,13 +27,12 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<!-- Important: Use <wbr> to mess with keywords. -->
|
<!-- Important: Use <wbr> to mess with keywords. -->
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -43,8 +42,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -160,7 +158,6 @@
|
||||||
<script src="assets/js/links.js"></script>
|
<script src="assets/js/links.js"></script>
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -29,13 +29,13 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
|
|
||||||
<!-- Important: Use <wbr> to mess with keywords. -->
|
<!-- Important: Use <wbr> to mess with keywords. -->
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -45,8 +45,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -78,8 +77,7 @@
|
||||||
|
|
||||||
<!-- Particles.js background -->
|
<!-- Particles.js background -->
|
||||||
|
|
||||||
<script id="particles-js" style="background-image: url("assets/img/black.jpg");height: 100%;background-position: center;background-size: cover;background-repeat: no-repeat;background-color: #000000;font-family: 'Montserrat Alternates', sans-serif;font-weight: bold;"
|
<script id="particles-js" style="background-image: url("assets/img/black.jpg");height: 100%;background-position: center;background-size: cover;background-repeat: no-repeat;background-color: #000000;font-family: 'Montserrat Alternates', sans-serif;font-weight: bold;" /> document.write(`
|
||||||
/> document.write(`
|
|
||||||
<div>
|
<div>
|
||||||
<h1>Privacy Policy for Holy Unblocker</h1>
|
<h1>Privacy Policy for Holy Unblocker</h1>
|
||||||
|
|
||||||
|
@ -345,7 +343,6 @@
|
||||||
<script src="assets/js/links.js"></script>
|
<script src="assets/js/links.js"></script>
|
||||||
<script src="assets/js/jquery.min.js"></script>
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="expr/surf.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,6 +27,8 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<span style=display:none data-cooking=cooks>Cuisines Often, a certain combination of ingredients forms the foundation of a particular cuisine. For example, Cantonese cuisine, based in southern China, makes much use of scallions, garlic, and ginger. Greek dishes often include garlic, olive oil, and oregano. Cuisines are often based on locally available ingredients. In the coastal city of Boston, for example, traditional favorites include such seafood dishes as clam chowder and lobster. Many cuisines reflect the variety of cultures in an area. In Louisiana, for example, such dishes as gumbo (a spicy stew) combine African American, Native American, and French cooking traditions. Preparation of ingredients Many ingredients must be prepared before cooking. Some fruits and vegetables must be peeled. Cooks may remove the skin, bones, and fat from meat or the shells from seafood. Cooks may also cut ingredients in a variety of ways, including dicing (cutting into small cubes) and mincing (chopping extremely fine). The size of the pieces helps determine how fast they cook, as well as the texture of the finished dish. Many cooks season food with salt, spices, and herbs before cooking. Ingredients must be prepared with safety in mind. Fruits and vegetables should generally be rinsed to remove any residues from agricultural chemicals. In addition, raw meats may contain disease-causing organisms. Proper cooking usually kills such organisms. But anything the meat touches can also become contaminated. Cooks must thus be careful when handling raw meat. They can help prevent food-borne illness by using soap and hot water to wash their hands, along with any surface that has touched raw meat.
|
||||||
|
</span>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
|
@ -99,20 +101,6 @@
|
||||||
<p class="text-white s-text-p2"><br>All<wbr>oy Pr<wbr>ox<wbr>y created by S<wbr>exyDu<wbr>ceD<wbr>uce
|
<p class="text-white s-text-p2"><br>All<wbr>oy Pr<wbr>ox<wbr>y created by S<wbr>exyDu<wbr>ceD<wbr>uce
|
||||||
(a very epic person) :D<br>All<wbr>oy v2.3</p>
|
(a very epic person) :D<br>All<wbr>oy v2.3</p>
|
||||||
</form>
|
</form>
|
||||||
<span style=display:none data-cooking=cooks>Cooking started 1.9 million years ago. Therefore, cooking is not something new to humans. Cooking started over a fire with no pots and pans or cooking utensils and now we have microwaves and stoves and special brushes to wipe on a marinade which was not even able to be comprehended 1.9 years ago. In between that time was the middle ages which had many advancements. Life was very different before cooking and has been very different since the beginning of cooking.
|
|
||||||
|
|
||||||
1.9 million years ago, given humans average sizes, had to spend forty eight percent of their life time in the “feeding process.” The feeding process does not include cooking. Cooking narrowed the time that humans had to spend in the feeding process to five percent. This change made it to where humans could spend less time in the feeding process and could do more valuable things with their time such as go out and hunt to grow bigger societies and other pursuits which ultimately lead to the beginning to the path of our modern brain. Cooking made food a lot easier to chew and digest. As a result of that we got more calorie benefit and a smaller digestive tract. All of this made cooking a vital part of human adaptation. The changes in human teeth happened so much faster than anything in the human body that scientists have come to the conclusion that this means that cooking was and has been passed down from generations and generations. Also, the oppressed women theory has been going on since the beginning of cooking when men went out and hunted and sought new things. Women at this time had to cook and do the gathering because of their lack of physically strength. So ever since cooking, even 1.9 million years ago, the roles of men and women have been a natural thing of life...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
... middle of paper ...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
...still be spending too much time eating and cooking. Different things in nature such as wood, spices, iron and chemicals that make up fire, which are just a few, helped start and continue cooking down the path that it’s going down. I think that cooking will continue to expand as technology advances. I am not sure how it will advance and change but I am sure we will have better more efficient stove tops and ovens.
|
|
||||||
|
|
||||||
In conclusion, cooking has evolved as technology has developed. But in the grand scheme of things we still have the same methods. Cooking helped the advancement of the human brain and the advancement of human teeth and our digestive tracts. Today we have restaurants, grocery stores, microwaves, and ovens. And all we started off with was a fire and a piece of meat with a stick stuck through it. Cooking was, is, and will be a vital part of the human life.
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/fonts/ionicons.min.css">
|
<link rel="stylesheet" href="assets/fonts/ionicons.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<iframe id="frame" style="visibility: hidden;"></iframe>
|
<iframe id="frame" style="visibility: hidden;"></iframe>
|
||||||
<noscript>You must enable javascript in your browser to view this webpage.</noscript>
|
<noscript>You must enable javascript in your browser to view this webpage.</noscript>
|
||||||
<!--New-->
|
<!--New-->
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<span style=display:none data-cooking=cooks>Methods Heat can transform the flavor and texture of ingredients. Browning meat and other ingredients, for example, involves complex chemical reactions. Fruits and vegetables contain sugars that caramelize when browned. The reaction in browning proteins, such as those in meat and poultry, is called the Maillard reaction after Louis Camille Maillard, the French chemist who discovered it. The Maillard reaction produces many new chemical compounds. These compounds give the food new flavors and aromas. The browned bits of food that stick to a pan are called fond, a French word meaning bottom. Many sauces make use of the rich, complex flavors of fond. Browning can only occur at temperatures above the boiling point of water, which is 212 °F (100 °C) at sea level. For this reason, moisture around the exterior of food must evaporate before the food can brown. Air and fat, as well as the metal surfaces of pans, can reach extremely high temperatures in browning. But cooking ingredients at high temperature for too long removes moisture, turning food dry and chewy. Skilled cooks will therefore carefully control both heat and moisture when cooking. Cooking with dry heat involves exposing food to hot air. As the air moves around the food’s surface, its heat is transferred to the cooler food. Roasting traditionally involved cooking large pieces of meat—or even a whole animal, such as a pig or a lamb—over an open fire. But today, roasting generally refers to cooking food in a hot oven. Roasting meat or vegetables in a high temperature oven—above 400 °F (205 °C)—causes the food to brown quickly. But high temperatures can also dry out food. Cooks thus sometimes brown meat and then finish it in a lower temperature oven to keep it moist inside. Cooks often roast ingredients on a rack above a roasting pan, enabling hot air to reach all sides of the food.</span>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
|
|
|
@ -11,13 +11,21 @@
|
||||||
:D">
|
:D">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/i.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/i.png">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
|
<style type="text/css">
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<!-- AL YT -->
|
<!-- AL YT -->
|
||||||
<script src="/expr/ch.js"></script>
|
<script src="/expr/ch.js"></script>
|
||||||
<script async src="https://arc.io/widget.js#2BzvQ1em"></script>
|
<script async src="https://arc.io/widget.js#2BzvQ1em"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="visibility: visible;"></iframe>
|
|
||||||
<span style=display:none data-cooking=cooks>Cooking started 1.9 million years ago. Therefore, cooking is not something new to humans. Cooking started over a fire with no pots and pans or cooking utensils and now we have microwaves and stoves and special brushes to wipe on a marinade which was not even able to be comprehended 1.9 years ago. In between that time was the middle ages which had many advancements. Life was very different before cooking and has been very different since the beginning of cooking.
|
<span style=display:none data-cooking=cooks>Cooking started 1.9 million years ago. Therefore, cooking is not something new to humans. Cooking started over a fire with no pots and pans or cooking utensils and now we have microwaves and stoves and special brushes to wipe on a marinade which was not even able to be comprehended 1.9 years ago. In between that time was the middle ages which had many advancements. Life was very different before cooking and has been very different since the beginning of cooking.
|
||||||
|
|
||||||
1.9 million years ago, given humans average sizes, had to spend forty eight percent of their life time in the “feeding process.” The feeding process does not include cooking. Cooking narrowed the time that humans had to spend in the feeding process to five percent. This change made it to where humans could spend less time in the feeding process and could do more valuable things with their time such as go out and hunt to grow bigger societies and other pursuits which ultimately lead to the beginning to the path of our modern brain. Cooking made food a lot easier to chew and digest. As a result of that we got more calorie benefit and a smaller digestive tract. All of this made cooking a vital part of human adaptation. The changes in human teeth happened so much faster than anything in the human body that scientists have come to the conclusion that this means that cooking was and has been passed down from generations and generations. Also, the oppressed women theory has been going on since the beginning of cooking when men went out and hunted and sought new things. Women at this time had to cook and do the gathering because of their lack of physically strength. So ever since cooking, even 1.9 million years ago, the roles of men and women have been a natural thing of life...
|
1.9 million years ago, given humans average sizes, had to spend forty eight percent of their life time in the “feeding process.” The feeding process does not include cooking. Cooking narrowed the time that humans had to spend in the feeding process to five percent. This change made it to where humans could spend less time in the feeding process and could do more valuable things with their time such as go out and hunt to grow bigger societies and other pursuits which ultimately lead to the beginning to the path of our modern brain. Cooking made food a lot easier to chew and digest. As a result of that we got more calorie benefit and a smaller digestive tract. All of this made cooking a vital part of human adaptation. The changes in human teeth happened so much faster than anything in the human body that scientists have come to the conclusion that this means that cooking was and has been passed down from generations and generations. Also, the oppressed women theory has been going on since the beginning of cooking when men went out and hunted and sought new things. Women at this time had to cook and do the gathering because of their lack of physically strength. So ever since cooking, even 1.9 million years ago, the roles of men and women have been a natural thing of life...
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
<!-- Assets -->
|
<!-- Assets -->
|
||||||
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
<script src="particles.js"></script>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
<script nomodule="" src="https://unpkg.com/ionicons@5.1.2/dist/ionicons/ionicons.js"></script>
|
||||||
<script src="assets/js/header.js"></script>
|
<script src="assets/js/header.js"></script>
|
||||||
|
@ -27,12 +27,11 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<iframe id="frame" style="display:block; visibility: hidden;"></iframe>
|
<!--New-->
|
||||||
<div>
|
<div>
|
||||||
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
<div class="header-dark" style="background-color: rgb(0,0,0);background-image: url("assets/img/black.jpg");">
|
||||||
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search" style="height: 100px;">
|
||||||
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler"
|
<div class="container"><a class="navbar-brand" style="font-family: 'Montserrat Alternates', sans-serif;font-size: 21px;margin: 10px;font-style: normal;font-weight: bold;" href="/">Ho​ly Unb​lock​er</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||||
data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
|
||||||
<div class="collapse navbar-collapse" id="navcol-1">
|
<div class="collapse navbar-collapse" id="navcol-1">
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
<!--Nav-->
|
<!--Nav-->
|
||||||
|
@ -42,8 +41,7 @@
|
||||||
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
<li class="nav-item" role="presentation"><a class="nav-link" href="/?d" style="font-family: 'Montserrat Alternates', sans-serif;">D​isc​ord</a></li>
|
||||||
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
<li id="ch" class="nav-item" role="presentation"><a class="nav-link" href="/?n" style="font-family: 'Montserrat Alternates', sans-serif;">Cha​tbox</a></li>
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;color: rgb(255,255,255);font-family: 'Montserrat Alternates', sans-serif;">More</a>
|
||||||
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50"
|
<div class="dropdown-menu" role="menu" style="background-color: rgb(33,30,30);font-family: 'Titillium Web', sans-serif;padding: 17%;padding-top: 10%;padding-bottom: 10%;"><a class="dropdown-item text-left text-white-50" role="presentation" href="/?k" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Kru​nk​er</a><a class="dropdown-item text-left text-white-50" role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
||||||
role="presentation" href="/?in" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Docs</a><a class="dropdown-item text-white-50" role="presentation" href="/?c" style="color: rgb(255,255,255);padding: 0%;font-family: Lato, sans-serif;">Cre​dits</a></div>
|
|
||||||
</li>
|
</li>
|
||||||
<!--Options Menu-->
|
<!--Options Menu-->
|
||||||
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
<li class="nav-item dropdown"><a class="dropdown-toggle nav-link text-white" data-toggle="dropdown" aria-expanded="false" href="#" style="opacity: 0.80;font-family: 'Montserrat Alternates', sans-serif;">Options</a>
|
||||||
|
@ -89,17 +87,17 @@
|
||||||
<p class="s-text-header" style="font-size: 46px;">Su<wbr>rf Free<wbr>ly</p>
|
<p class="s-text-header" style="font-size: 46px;">Su<wbr>rf Free<wbr>ly</p>
|
||||||
<p class="s-text-p1" style="font-family: 'Montserrat Alternates', sans-serif;">Choose which proxy you would like to use. Below is some information.</p>
|
<p class="s-text-p1" style="font-family: 'Montserrat Alternates', sans-serif;">Choose which proxy you would like to use. Below is some information.</p>
|
||||||
<p class="text-white" style="font-size: 20px;font-family: Lato, sans-serif;">More Information:<br></p>
|
<p class="text-white" style="font-size: 20px;font-family: Lato, sans-serif;">More Information:<br></p>
|
||||||
<p class="text-hb-light s-text-p2" style="font-family: Lato, sans-serif;">A​llo​y: Di​sco​rd (Mostly Full), Yo​uTu​be (Full), etc.<br><br>Vi<wbr>a: Alter<wbr>native pro<wbr>xy which suppo<wbr>rts many ga<wbr>me si<wbr>tes, etc.<br><br>Nod​e: Secondary
|
<p class="text-hb-light s-text-p2" style="font-family: Lato, sans-serif;">A​llo​y: Di​sco​rd (Mostly Full), Yo​uTu​be (Full), etc.<br><br>Vi<wbr>a: Alter<wbr>native pro<wbr>xy which suppo<wbr>rts many ga<wbr>me si<wbr>tes, etc.<br><br>Nod​e: Secondary pr​oxy compared to Al​loy, PM and PD.<br><br>P<wbr>M Pro<wbr>xy: Disc<wbr>ord, Yout<wbr>ube
|
||||||
pr​oxy compared to Al​loy, PM and PD.<br><br>P<wbr>M Pro<wbr>xy: Disc<wbr>ord, Yout<wbr>ube (limited), etc.<br>
|
(limited), etc.<br>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-white s-text-p2">Many sites work with this. Join the T<wbr>N disc<wbr>ord for updated H<wbr>B sites and more. Explore!</strong><br>T<wbr>N D<wbr>isco<wbr>rd:</p>
|
<p class="text-white s-text-p2">Many sites work with this. Join the T<wbr>N disc<wbr>ord for updated H<wbr>B sites and more. Explore!</strong><br>T<wbr>N D<wbr>isco<wbr>rd:</p>
|
||||||
<a class="text-hb s-text-p2" id="tnlink">https://dis​cord.c​om/invite/Dw​6C7p​5</a><br>
|
<a class="text-hb s-text-p2" id="tnlink">https://dis​cord.c​om/invite/Dw​6C7p​5</a><br>
|
||||||
<div style="margin: 2%;padding: 1px;">
|
<div style="margin: 2%;padding: 1px;">
|
||||||
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1" role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif;" href="/?a">Al<wbr>loy Pro<wbr>xy</a>
|
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1" role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif;" href="/?a">Al<wbr>loy Pro<wbr>xy</a>
|
||||||
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1" role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif; margin-left: 5px;" href="/?e">V<wbr>ia Un<wbr>blo<wbr>cker</a>
|
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1" role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif; margin-left: 5px;" href="/?e">V<wbr>ia Un<wbr>blo<wbr>cker</a>
|
||||||
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1" role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif; margin-left: 5px;" href="/?b">No<wbr>de Un<wbr>bloc<wbr>ker</a>
|
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1" role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif; margin-left: 5px;" href="/?b">No<wbr>de Un<wbr>bloc<wbr>ker</a>
|
||||||
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1 " role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif; margin-left: 5px; " href="/?p">PM Pro<wbr>xy</a>
|
<a class="btn btn-group text-hb hb-border-color glow-on-hover rounded-1 " role="button" data-bs-hover-animate="pulse" style="background-color: rgb(24,26,28);font-family: 'Montserrat Alternates', sans-serif; margin-left: 5px; " href="/?p">PM Pro<wbr>xy</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span style=display:none data-cooking=cooks>Cooking started 1.9 million years ago. Therefore, cooking is not something new to humans. Cooking started over a fire with no pots and pans or cooking utensils and now we have microwaves and stoves and special brushes to wipe on a marinade which was not even able to be comprehended 1.9 years ago. In between that time was the middle ages which had many advancements. Life was very different before cooking and has been very different since the beginning of cooking.
|
<span style=display:none data-cooking=cooks>Cooking started 1.9 million years ago. Therefore, cooking is not something new to humans. Cooking started over a fire with no pots and pans or cooking utensils and now we have microwaves and stoves and special brushes to wipe on a marinade which was not even able to be comprehended 1.9 years ago. In between that time was the middle ages which had many advancements. Life was very different before cooking and has been very different since the beginning of cooking.
|
||||||
|
|
||||||
|
|
1541
public/particles.js
Normal file
1541
public/particles.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,31 +2,3 @@ User-agent: *
|
||||||
Allow: /
|
Allow: /
|
||||||
Sitemap: https://quiteafancyemerald.com
|
Sitemap: https://quiteafancyemerald.com
|
||||||
Sitemap: https://holyubofficial.net
|
Sitemap: https://holyubofficial.net
|
||||||
|
|
||||||
User-agent: Googlebot
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://quiteafancyemerald.com
|
|
||||||
Sitemap: https://holyubofficial.net
|
|
||||||
|
|
||||||
User-agent: DuckDuckBot
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://quiteafancyemerald.com
|
|
||||||
Sitemap: https://holyubofficial.net
|
|
||||||
|
|
||||||
User-agent: Bingbot
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://quiteafancyemerald.com
|
|
||||||
Sitemap: https://holyubofficial.net
|
|
||||||
|
|
||||||
User-agent: Slurp
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://quiteafancyemerald.com
|
|
||||||
Sitemap: https://holyubofficial.net
|
|
||||||
|
|
||||||
User-agent: Baiduspider
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://quiteafancyemerald.com
|
|
||||||
Sitemap: https://holyubofficial.net
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,122 +2,62 @@
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?a</loc>
|
<loc>https://quiteafancyemerald.com/?a</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?b</loc>
|
<loc>https://quiteafancyemerald.com/?b</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?z</loc>
|
<loc>https://quiteafancyemerald.com/?z</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
<priority>0.9<priority>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?y</loc>
|
<loc>https://quiteafancyemerald.com/?y</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?d</loc>
|
<loc>https://quiteafancyemerald.com/?d</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/</loc>
|
<loc>https://quiteafancyemerald.com/</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
<priority>0.9<priority>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?k</loc>
|
<loc>https://quiteafancyemerald.com/?k</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?g</loc>
|
<loc>https://quiteafancyemerald.com/?g</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?e</loc>
|
<loc>https://quiteafancyemerald.com/?e</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://quiteafancyemerald.com/?in</loc>
|
<loc>https://quiteafancyemerald.com/?in</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.9<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?a</loc>
|
<loc>https://holyubofficial.net/?a</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?b</loc>
|
<loc>https://holyubofficial.net/?b</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?z</loc>
|
<loc>https://holyubofficial.net/?z</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.9<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?y</loc>
|
<loc>https://holyubofficial.net/?y</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?d</loc>
|
<loc>https://holyubofficial.net/?d</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/</loc>
|
<loc>https://holyubofficial.net/</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?k</loc>
|
<loc>https://holyubofficial.net/?k</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?g</loc>
|
<loc>https://holyubofficial.net/?g</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?e</loc>
|
<loc>https://holyubofficial.net/?e</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.8<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://holyubofficial.net/?in</loc>
|
<loc>https://holyubofficial.net/?in</loc>
|
||||||
<changefreq>daily</changefreq>
|
|
||||||
<priority>0.9<priority>
|
|
||||||
<lastmod>2020-11-11</lastmod>
|
|
||||||
</url>
|
</url>
|
||||||
</urlset>
|
</urlset>
|
232
src/cpu.js
232
src/cpu.js
|
@ -1,232 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// CPU class
|
|
||||||
var CPU = function(gameboy) {
|
|
||||||
this.gameboy = gameboy;
|
|
||||||
|
|
||||||
this.r = {A:0, F: 0, B:0, C:0, D:0, E:0, H:0, L:0, pc:0, sp:0};
|
|
||||||
this.IME = true;
|
|
||||||
this.clock = {c: 0, serial: 0};
|
|
||||||
this.isHalted = false;
|
|
||||||
this.isPaused = false;
|
|
||||||
this.usingBootRom = false;
|
|
||||||
|
|
||||||
this.createDevices();
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.INTERRUPTS = {
|
|
||||||
VBLANK: 0,
|
|
||||||
LCDC: 1,
|
|
||||||
TIMER: 2,
|
|
||||||
SERIAL: 3,
|
|
||||||
HILO: 4
|
|
||||||
};
|
|
||||||
CPU.interruptRoutines = {
|
|
||||||
0: function(p){GameboyJS.cpuOps.RSTn(p, 0x40);},
|
|
||||||
1: function(p){GameboyJS.cpuOps.RSTn(p, 0x48);},
|
|
||||||
2: function(p){GameboyJS.cpuOps.RSTn(p, 0x50);},
|
|
||||||
3: function(p){GameboyJS.cpuOps.RSTn(p, 0x58);},
|
|
||||||
4: function(p){GameboyJS.cpuOps.RSTn(p, 0x60);}
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.createDevices = function() {
|
|
||||||
this.memory = new GameboyJS.Memory(this);
|
|
||||||
this.timer = new GameboyJS.Timer(this, this.memory);
|
|
||||||
this.apu = new GameboyJS.APU(this.memory);
|
|
||||||
|
|
||||||
this.SERIAL_INTERNAL_INSTR = 512; // instr to wait per bit if internal clock
|
|
||||||
this.enableSerial = 0;
|
|
||||||
this.serialHandler = GameboyJS.ConsoleSerial;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.reset = function() {
|
|
||||||
this.memory.reset();
|
|
||||||
|
|
||||||
this.r.sp = 0xFFFE;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.loadRom = function(data) {
|
|
||||||
this.memory.setRomData(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.getRamSize = function() {
|
|
||||||
var size = 0;
|
|
||||||
switch (this.memory.rb(0x149)) {
|
|
||||||
case 1:
|
|
||||||
size = 2048;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
size = 2048 * 4;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
size = 2048 * 16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.getGameName = function() {
|
|
||||||
var name = '';
|
|
||||||
for (var i = 0x134; i < 0x143; i++) {
|
|
||||||
var char = this.memory.rb(i) || 32;
|
|
||||||
name += String.fromCharCode(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start the execution of the emulator
|
|
||||||
CPU.prototype.run = function() {
|
|
||||||
if (this.usingBootRom) {
|
|
||||||
this.r.pc = 0x0000;
|
|
||||||
} else {
|
|
||||||
this.r.pc = 0x0100;
|
|
||||||
}
|
|
||||||
this.frame();
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.stop = function() {
|
|
||||||
clearTimeout(this.nextFrameTimer);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fetch-and-execute loop
|
|
||||||
// Will execute instructions for the duration of a frame
|
|
||||||
//
|
|
||||||
// The screen unit will notify the vblank period which
|
|
||||||
// is considered the end of a frame
|
|
||||||
//
|
|
||||||
// The function is called on a regular basis with a timeout
|
|
||||||
CPU.prototype.frame = function() {
|
|
||||||
if (!this.isPaused) {
|
|
||||||
this.nextFrameTimer = setTimeout(this.frame.bind(this), 1000 / GameboyJS.Screen.physics.FREQUENCY);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var vblank = false;
|
|
||||||
while (!vblank) {
|
|
||||||
var oldInstrCount = this.clock.c;
|
|
||||||
if (!this.isHalted) {
|
|
||||||
var opcode = this.fetchOpcode();
|
|
||||||
GameboyJS.opcodeMap[opcode](this);
|
|
||||||
this.r.F &= 0xF0; // tmp fix
|
|
||||||
|
|
||||||
if (this.enableSerial) {
|
|
||||||
var instr = this.clock.c - oldInstrCount;
|
|
||||||
this.clock.serial += instr;
|
|
||||||
if (this.clock.serial >= 8 * this.SERIAL_INTERNAL_INSTR) {
|
|
||||||
this.endSerialTransfer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.clock.c += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
var elapsed = this.clock.c - oldInstrCount;
|
|
||||||
vblank = this.gpu.update(elapsed);
|
|
||||||
this.timer.update(elapsed);
|
|
||||||
this.input.update();
|
|
||||||
this.apu.update(elapsed);
|
|
||||||
this.checkInterrupt();
|
|
||||||
}
|
|
||||||
this.clock.c = 0;
|
|
||||||
} catch (e) {
|
|
||||||
this.gameboy.handleException(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.fetchOpcode = function() {
|
|
||||||
var opcode = this.memory.rb(this.r.pc++);
|
|
||||||
if (opcode === undefined) {console.log(opcode + ' at ' + (this.r.pc-1).toString(16));this.stop();return;}
|
|
||||||
if (!GameboyJS.opcodeMap[opcode]) {
|
|
||||||
console.error('Unknown opcode '+opcode.toString(16)+' at address '+(this.r.pc-1).toString(16)+', stopping execution...');
|
|
||||||
this.stop();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return opcode;
|
|
||||||
};
|
|
||||||
|
|
||||||
// read register
|
|
||||||
CPU.prototype.rr = function(register) {
|
|
||||||
return this.r[register];
|
|
||||||
};
|
|
||||||
|
|
||||||
// write register
|
|
||||||
CPU.prototype.wr = function(register, value) {
|
|
||||||
this.r[register] = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.halt = function() {
|
|
||||||
this.isHalted = true;
|
|
||||||
};
|
|
||||||
CPU.prototype.unhalt = function() {
|
|
||||||
this.isHalted = false;
|
|
||||||
};
|
|
||||||
CPU.prototype.pause = function() {
|
|
||||||
this.isPaused = true;
|
|
||||||
};
|
|
||||||
CPU.prototype.unpause = function() {
|
|
||||||
if (this.isPaused) {
|
|
||||||
this.isPaused = false;
|
|
||||||
this.frame();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Look for interrupt flags
|
|
||||||
CPU.prototype.checkInterrupt = function() {
|
|
||||||
if (!this.IME) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var i = 0; i < 5; i++) {
|
|
||||||
var IFval = this.memory.rb(0xFF0F);
|
|
||||||
if (GameboyJS.Util.readBit(IFval, i) && this.isInterruptEnable(i)) {
|
|
||||||
IFval &= (0xFF - (1<<i));
|
|
||||||
this.memory.wb(0xFF0F, IFval);
|
|
||||||
this.disableInterrupts();
|
|
||||||
this.clock.c += 4; // 20 clocks to serve interrupt, with 16 for RSTn
|
|
||||||
CPU.interruptRoutines[i](this);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set an interrupt flag
|
|
||||||
CPU.prototype.requestInterrupt = function(type) {
|
|
||||||
var IFval = this.memory.rb(0xFF0F);
|
|
||||||
IFval |= (1 << type)
|
|
||||||
this.memory.wb(0xFF0F, IFval) ;
|
|
||||||
this.unhalt();
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.isInterruptEnable = function(type) {
|
|
||||||
return GameboyJS.Util.readBit(this.memory.rb(0xFFFF), type) != 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.enableInterrupts = function() {
|
|
||||||
this.IME = true;
|
|
||||||
};
|
|
||||||
CPU.prototype.disableInterrupts = function() {
|
|
||||||
this.IME = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.enableSerialTransfer = function() {
|
|
||||||
this.enableSerial = 1;
|
|
||||||
this.clock.serial = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.endSerialTransfer = function() {
|
|
||||||
this.enableSerial = 0;
|
|
||||||
var data = this.memory.rb(0xFF01);
|
|
||||||
this.memory.wb(0xFF02, 0);
|
|
||||||
this.serialHandler.out(data);
|
|
||||||
this.memory.wb(0xFF01, this.serialHandler.in());
|
|
||||||
};
|
|
||||||
|
|
||||||
CPU.prototype.resetDivTimer = function() {
|
|
||||||
this.timer.resetDiv();
|
|
||||||
};
|
|
||||||
GameboyJS.CPU = CPU;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
73
src/debug.js
73
src/debug.js
|
@ -1,73 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var Debug = {};
|
|
||||||
// Output a range of 16 memory addresses
|
|
||||||
Debug.view_memory = function(addr, gameboy) {
|
|
||||||
var memory = gameboy.cpu.memory;
|
|
||||||
addr = addr & 0xFFF0;
|
|
||||||
var pad = '00';
|
|
||||||
var str = addr.toString(16) + ':';
|
|
||||||
for (var i = addr; i < addr + 0x10; i++) {
|
|
||||||
if ((i & 0x1) == 0) {
|
|
||||||
str += ' ';
|
|
||||||
}
|
|
||||||
var val = memory[i] || 0;
|
|
||||||
|
|
||||||
val = val.toString(16);
|
|
||||||
str += pad.substring(val.length) + val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
Debug.view_tile = function(gameboy, index, dataStart) {
|
|
||||||
var memory = gameboy.cpu.memory;
|
|
||||||
var screen = gameboy.screen;
|
|
||||||
var LCDC = screen.deviceram(screen.LCDC);
|
|
||||||
if (typeof dataStart === 'undefined') {
|
|
||||||
dataStart = 0x8000;
|
|
||||||
if (!GameboyJS.Util.readBit(LCDC, 4)) {
|
|
||||||
dataStart = 0x8800;
|
|
||||||
index = GameboyJS.cpuOps._getSignedValue(index) + 128;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var tileData = screen.readTileData(index, dataStart);
|
|
||||||
|
|
||||||
var pixelData = new Array(8 * 8)
|
|
||||||
for (var line = 0; line < 8; line++) {
|
|
||||||
var b1 = tileData.shift();
|
|
||||||
var b2 = tileData.shift();
|
|
||||||
|
|
||||||
for (var pixel = 0; pixel < 8; pixel++) {
|
|
||||||
var mask = (1 << (7-pixel));
|
|
||||||
var colorValue = ((b1 & mask) >> (7-pixel)) + ((b2 & mask) >> (7-pixel))*2;
|
|
||||||
pixelData[line * 8 + pixel] = colorValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = 0;
|
|
||||||
while (pixelData.length) {
|
|
||||||
console.log(i++ + ' ' + pixelData.splice(0, 8).join(''));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Debug.list_visible_sprites = function(gameboy) {
|
|
||||||
var memory = gameboy.cpu.memory;
|
|
||||||
var indexes = new Array();
|
|
||||||
for (var i = 0xFE00; i < 0xFE9F; i += 4) {
|
|
||||||
var x = memory.oamram(i + 1);
|
|
||||||
var y = memory.oamram(i);
|
|
||||||
var tileIndex = memory.oamram(i + 2);
|
|
||||||
if (x == 0 || x >= 168) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
indexes.push({oamIndex:i, x:x, y:y, tileIndex:tileIndex});
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexes;
|
|
||||||
};
|
|
||||||
GameboyJS.Debug = Debug;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,388 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
var Screen;
|
|
||||||
var GPU = function(screen, cpu) {
|
|
||||||
this.cpu = cpu;
|
|
||||||
this.screen = screen;
|
|
||||||
|
|
||||||
this.LCDC= 0xFF40;
|
|
||||||
this.STAT= 0xFF41;
|
|
||||||
this.SCY = 0xFF42;
|
|
||||||
this.SCX = 0xFF43;
|
|
||||||
this.LY = 0xFF44;
|
|
||||||
this.LYC = 0xFF45;
|
|
||||||
this.BGP = 0xFF47;
|
|
||||||
this.OBP0= 0xFF48;
|
|
||||||
this.OBP1= 0xFF49;
|
|
||||||
this.WY = 0xFF4A;
|
|
||||||
this.WX = 0xFF4B;
|
|
||||||
|
|
||||||
this.vram = cpu.memory.vram.bind(cpu.memory);
|
|
||||||
|
|
||||||
this.OAM_START = 0xFE00;
|
|
||||||
this.OAM_END = 0xFE9F;
|
|
||||||
this.deviceram = cpu.memory.deviceram.bind(cpu.memory);
|
|
||||||
this.oamram = cpu.memory.oamram.bind(cpu.memory);
|
|
||||||
this.VBLANK_TIME = 70224;
|
|
||||||
this.clock = 0;
|
|
||||||
this.mode = 2;
|
|
||||||
this.line = 0;
|
|
||||||
|
|
||||||
Screen = GameboyJS.Screen;
|
|
||||||
this.buffer = new Array(Screen.physics.WIDTH * Screen.physics.HEIGHT);
|
|
||||||
this.tileBuffer = new Array(8);
|
|
||||||
this.bgTileCache = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.tilemap = {
|
|
||||||
HEIGHT: 32,
|
|
||||||
WIDTH: 32,
|
|
||||||
START_0: 0x9800,
|
|
||||||
START_1: 0x9C00,
|
|
||||||
LENGTH: 0x0400 // 1024 bytes = 32*32
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.update = function(clockElapsed) {
|
|
||||||
this.clock += clockElapsed;
|
|
||||||
var vblank = false;
|
|
||||||
|
|
||||||
switch (this.mode) {
|
|
||||||
case 0: // HBLANK
|
|
||||||
if (this.clock >= 204) {
|
|
||||||
this.clock -= 204;
|
|
||||||
this.line++;
|
|
||||||
this.updateLY();
|
|
||||||
if (this.line == 144) {
|
|
||||||
this.setMode(1);
|
|
||||||
vblank = true;
|
|
||||||
this.cpu.requestInterrupt(GameboyJS.CPU.INTERRUPTS.VBLANK);
|
|
||||||
this.drawFrame();
|
|
||||||
} else {
|
|
||||||
this.setMode(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1: // VBLANK
|
|
||||||
if (this.clock >= 456) {
|
|
||||||
this.clock -= 456;
|
|
||||||
this.line++;
|
|
||||||
if (this.line > 153) {
|
|
||||||
this.line = 0;
|
|
||||||
this.setMode(2);
|
|
||||||
}
|
|
||||||
this.updateLY();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 2: // SCANLINE OAM
|
|
||||||
if (this.clock >= 80) {
|
|
||||||
this.clock -= 80;
|
|
||||||
this.setMode(3);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3: // SCANLINE VRAM
|
|
||||||
if (this.clock >= 172) {
|
|
||||||
this.clock -= 172;
|
|
||||||
this.drawScanLine(this.line);
|
|
||||||
this.setMode(0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vblank;
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.updateLY = function() {
|
|
||||||
this.deviceram(this.LY, this.line);
|
|
||||||
var STAT = this.deviceram(this.STAT);
|
|
||||||
if (this.deviceram(this.LY) == this.deviceram(this.LYC)) {
|
|
||||||
this.deviceram(this.STAT, STAT | (1 << 2));
|
|
||||||
if (STAT & (1 << 6)) {
|
|
||||||
this.cpu.requestInterrupt(GameboyJS.CPU.INTERRUPTS.LCDC);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.deviceram(this.STAT, STAT & (0xFF - (1 << 2)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.setMode = function(mode) {
|
|
||||||
this.mode = mode;
|
|
||||||
var newSTAT = this.deviceram(this.STAT);
|
|
||||||
newSTAT &= 0xFC;
|
|
||||||
newSTAT |= mode;
|
|
||||||
this.deviceram(this.STAT, newSTAT);
|
|
||||||
|
|
||||||
if (mode < 3) {
|
|
||||||
if (newSTAT & (1 << (3+mode))) {
|
|
||||||
this.cpu.requestInterrupt(GameboyJS.CPU.INTERRUPTS.LCDC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Push one scanline into the main buffer
|
|
||||||
GPU.prototype.drawScanLine = function(line) {
|
|
||||||
var LCDC = this.deviceram(this.LCDC);
|
|
||||||
var enable = GameboyJS.Util.readBit(LCDC, 7);
|
|
||||||
if (enable) {
|
|
||||||
var lineBuffer = new Array(Screen.physics.WIDTH);
|
|
||||||
this.drawBackground(LCDC, line, lineBuffer);
|
|
||||||
this.drawSprites(LCDC, line, lineBuffer);
|
|
||||||
// TODO draw a line for the window here too
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.drawFrame = function() {
|
|
||||||
var LCDC = this.deviceram(this.LCDC);
|
|
||||||
var enable = GameboyJS.Util.readBit(LCDC, 7);
|
|
||||||
if (enable) {
|
|
||||||
//this.drawSprites(LCDC);
|
|
||||||
this.drawWindow(LCDC);
|
|
||||||
}
|
|
||||||
this.bgTileCache = {};
|
|
||||||
this.screen.render(this.buffer);
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.drawBackground = function(LCDC, line, lineBuffer) {
|
|
||||||
if (!GameboyJS.Util.readBit(LCDC, 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapStart = GameboyJS.Util.readBit(LCDC, 3) ? GPU.tilemap.START_1 : GPU.tilemap.START_0;
|
|
||||||
|
|
||||||
var dataStart, signedIndex = false;
|
|
||||||
if (GameboyJS.Util.readBit(LCDC, 4)) {
|
|
||||||
dataStart = 0x8000;
|
|
||||||
} else {
|
|
||||||
dataStart = 0x8800;
|
|
||||||
signedIndex = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var bgx = this.deviceram(this.SCX);
|
|
||||||
var bgy = this.deviceram(this.SCY);
|
|
||||||
var tileLine = ((line + bgy) & 7);
|
|
||||||
|
|
||||||
// browse BG tilemap for the line to render
|
|
||||||
var tileRow = ((((bgy + line) / 8) | 0) & 0x1F);
|
|
||||||
var firstTile = ((bgx / 8) | 0) + 32 * tileRow;
|
|
||||||
var lastTile = firstTile + Screen.physics.WIDTH / 8 + 1;
|
|
||||||
if ((lastTile & 0x1F) < (firstTile & 0x1F)) {
|
|
||||||
lastTile -= 32;
|
|
||||||
}
|
|
||||||
var x = (firstTile & 0x1F) * 8 - bgx; // x position of the first tile's leftmost pixel
|
|
||||||
for (var i = firstTile; i != lastTile; i++, (i & 0x1F) == 0 ? i-=32 : null) {
|
|
||||||
var tileIndex = this.vram(i + mapStart);
|
|
||||||
|
|
||||||
if (signedIndex) {
|
|
||||||
tileIndex = GameboyJS.Util.getSignedValue(tileIndex) + 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to retrieve the tile data from the cache, or use readTileData() to read from ram
|
|
||||||
// TODO find a better cache system now that the BG is rendered line by line
|
|
||||||
var tileData = this.bgTileCache[tileIndex] || (this.bgTileCache[tileIndex] = this.readTileData(tileIndex, dataStart));
|
|
||||||
|
|
||||||
this.drawTileLine(tileData, tileLine);
|
|
||||||
this.copyBGTileLine(lineBuffer, this.tileBuffer, x);
|
|
||||||
x += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.copyLineToBuffer(lineBuffer, line);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy a tile line from a tileBuffer to a line buffer, at a given x position
|
|
||||||
GPU.prototype.copyBGTileLine = function(lineBuffer, tileBuffer, x) {
|
|
||||||
// copy tile line to buffer
|
|
||||||
for (var k = 0; k < 8; k++, x++) {
|
|
||||||
if (x < 0 || x >= Screen.physics.WIDTH) continue;
|
|
||||||
lineBuffer[x] = tileBuffer[k];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy a scanline into the main buffer
|
|
||||||
GPU.prototype.copyLineToBuffer = function(lineBuffer, line) {
|
|
||||||
var bgPalette = GPU.getPalette(this.deviceram(this.BGP));
|
|
||||||
|
|
||||||
for (var x = 0; x < Screen.physics.WIDTH; x++) {
|
|
||||||
var color = lineBuffer[x];
|
|
||||||
this.drawPixel(x, line, bgPalette[color]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Write a line of a tile (8 pixels) into a buffer array
|
|
||||||
GPU.prototype.drawTileLine = function(tileData, line, xflip, yflip) {
|
|
||||||
xflip = xflip | 0;
|
|
||||||
yflip = yflip | 0;
|
|
||||||
var l = yflip ? 7 - line : line;
|
|
||||||
var byteIndex = l * 2;
|
|
||||||
var b1 = tileData[byteIndex++];
|
|
||||||
var b2 = tileData[byteIndex++];
|
|
||||||
|
|
||||||
var offset = 8;
|
|
||||||
for (var pixel = 0; pixel < 8; pixel++) {
|
|
||||||
offset--;
|
|
||||||
var mask = (1 << offset);
|
|
||||||
var colorValue = ((b1 & mask) >> offset) + ((b2 & mask) >> offset)*2;
|
|
||||||
var p = xflip ? offset : pixel;
|
|
||||||
this.tileBuffer[p] = colorValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.drawSprites = function(LCDC, line, lineBuffer) {
|
|
||||||
if (!GameboyJS.Util.readBit(LCDC, 1)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var spriteHeight = GameboyJS.Util.readBit(LCDC, 2) ? 16 : 8;
|
|
||||||
|
|
||||||
var sprites = new Array();
|
|
||||||
for (var i = this.OAM_START; i < this.OAM_END && sprites.length < 10; i += 4) {
|
|
||||||
var y = this.oamram(i);
|
|
||||||
var x = this.oamram(i+1);
|
|
||||||
var index = this.oamram(i+2);
|
|
||||||
var flags = this.oamram(i+3);
|
|
||||||
|
|
||||||
if (y - 16 > line || y - 16 < line - spriteHeight) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sprites.push({x:x, y:y, index:index, flags:flags})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sprites.length == 0) return;
|
|
||||||
|
|
||||||
// cache object to store read tiles from this frame
|
|
||||||
var cacheTile = {};
|
|
||||||
var spriteLineBuffer = new Array(Screen.physics.WIDTH);
|
|
||||||
|
|
||||||
for (var i = 0; i < sprites.length; i++) {
|
|
||||||
var sprite = sprites[i];
|
|
||||||
var tileLine = line - sprite.y + 16;
|
|
||||||
var paletteNumber = GameboyJS.Util.readBit(flags, 4);
|
|
||||||
var xflip = GameboyJS.Util.readBit(sprite.flags, 5);
|
|
||||||
var yflip = GameboyJS.Util.readBit(sprite.flags, 6);
|
|
||||||
var tileData = cacheTile[sprite.index] || (cacheTile[sprite.index] = this.readTileData(sprite.index, 0x8000, spriteHeight * 2));
|
|
||||||
this.drawTileLine(tileData, tileLine, xflip, yflip);
|
|
||||||
this.copySpriteTileLine(spriteLineBuffer, this.tileBuffer, sprite.x - 8, paletteNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.copySpriteLineToBuffer(spriteLineBuffer, line);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy a tile line from a tileBuffer to a line buffer, at a given x position
|
|
||||||
GPU.prototype.copySpriteTileLine = function(lineBuffer, tileBuffer, x, palette) {
|
|
||||||
// copy tile line to buffer
|
|
||||||
for (var k = 0; k < 8; k++, x++) {
|
|
||||||
if (x < 0 || x >= Screen.physics.WIDTH || tileBuffer[k] == 0) continue;
|
|
||||||
lineBuffer[x] = {color:tileBuffer[k], palette: palette};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy a sprite scanline into the main buffer
|
|
||||||
GPU.prototype.copySpriteLineToBuffer = function(spriteLineBuffer, line) {
|
|
||||||
var spritePalettes = {};
|
|
||||||
spritePalettes[0] = GPU.getPalette(this.deviceram(this.OBP0));
|
|
||||||
spritePalettes[1] = GPU.getPalette(this.deviceram(this.OBP1));
|
|
||||||
|
|
||||||
for (var x = 0; x < Screen.physics.WIDTH; x++) {
|
|
||||||
if (!spriteLineBuffer[x]) continue;
|
|
||||||
var color = spriteLineBuffer[x].color;
|
|
||||||
if (color === 0) continue;
|
|
||||||
var paletteNumber = spriteLineBuffer[x].palette;
|
|
||||||
this.drawPixel(x, line, spritePalettes[paletteNumber][color]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.drawTile = function(tileData, x, y, buffer, bufferWidth, xflip, yflip, spriteMode) {
|
|
||||||
xflip = xflip | 0;
|
|
||||||
yflip = yflip | 0;
|
|
||||||
spriteMode = spriteMode | 0;
|
|
||||||
var byteIndex = 0;
|
|
||||||
for (var line = 0; line < 8; line++) {
|
|
||||||
var l = yflip ? 7 - line : line;
|
|
||||||
var b1 = tileData[byteIndex++];
|
|
||||||
var b2 = tileData[byteIndex++];
|
|
||||||
|
|
||||||
for (var pixel = 0; pixel < 8; pixel++) {
|
|
||||||
var mask = (1 << (7-pixel));
|
|
||||||
var colorValue = ((b1 & mask) >> (7-pixel)) + ((b2 & mask) >> (7-pixel))*2;
|
|
||||||
if (spriteMode && colorValue == 0) continue;
|
|
||||||
var p = xflip ? 7 - pixel : pixel;
|
|
||||||
var bufferIndex = (x + p) + (y + l) * bufferWidth;
|
|
||||||
buffer[bufferIndex] = colorValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// get an array of tile bytes data (16 entries for 8*8px)
|
|
||||||
GPU.prototype.readTileData = function(tileIndex, dataStart, tileSize) {
|
|
||||||
tileSize = tileSize || 0x10; // 16 bytes / tile by default (8*8 px)
|
|
||||||
var tileData = new Array();
|
|
||||||
|
|
||||||
var tileAddressStart = dataStart + (tileIndex * 0x10);
|
|
||||||
for (var i = tileAddressStart; i < tileAddressStart + tileSize; i++) {
|
|
||||||
tileData.push(this.vram(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tileData;
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.drawWindow = function(LCDC) {
|
|
||||||
if (!GameboyJS.Util.readBit(LCDC, 5)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buffer = new Array(256*256);
|
|
||||||
var mapStart = GameboyJS.Util.readBit(LCDC, 6) ? GPU.tilemap.START_1 : GPU.tilemap.START_0;
|
|
||||||
|
|
||||||
var dataStart, signedIndex = false;
|
|
||||||
if (GameboyJS.Util.readBit(LCDC, 4)) {
|
|
||||||
dataStart = 0x8000;
|
|
||||||
} else {
|
|
||||||
dataStart = 0x8800;
|
|
||||||
signedIndex = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// browse Window tilemap
|
|
||||||
for (var i = 0; i < GPU.tilemap.LENGTH; i++) {
|
|
||||||
var tileIndex = this.vram(i + mapStart);
|
|
||||||
|
|
||||||
if (signedIndex) {
|
|
||||||
tileIndex = GameboyJS.Util.getSignedValue(tileIndex) + 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tileData = this.readTileData(tileIndex, dataStart);
|
|
||||||
var x = i % GPU.tilemap.WIDTH;
|
|
||||||
var y = (i / GPU.tilemap.WIDTH) | 0;
|
|
||||||
this.drawTile(tileData, x * 8, y * 8, buffer, 256);
|
|
||||||
}
|
|
||||||
|
|
||||||
var wx = this.deviceram(this.WX) - 7;
|
|
||||||
var wy = this.deviceram(this.WY);
|
|
||||||
for (var x = Math.max(0, -wx); x < Math.min(Screen.physics.WIDTH, Screen.physics.WIDTH - wx); x++) {
|
|
||||||
for (var y = Math.max(0, -wy); y < Math.min(Screen.physics.HEIGHT, Screen.physics.HEIGHT - wy); y++) {
|
|
||||||
var color = buffer[(x & 255) + (y & 255) * 256];
|
|
||||||
this.drawPixel(x + wx, y + wy, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.drawPixel = function(x, y, color) {
|
|
||||||
this.buffer[y * 160 + x] = color;
|
|
||||||
};
|
|
||||||
|
|
||||||
GPU.prototype.getPixel = function(x, y) {
|
|
||||||
return this.buffer[y * 160 + x];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the palette mapping from a given palette byte as stored in memory
|
|
||||||
// A palette will map a tile color to a final palette color index
|
|
||||||
// used with Screen.colors to get a shade of grey
|
|
||||||
GPU.getPalette = function(paletteByte) {
|
|
||||||
var palette = [];
|
|
||||||
for (var i = 0; i < 8; i += 2) {
|
|
||||||
var shade = (paletteByte & (3 << i)) >> i;
|
|
||||||
palette.push(shade);
|
|
||||||
}
|
|
||||||
return palette;
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.GPU = GPU;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,70 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Screen device
|
|
||||||
var Screen = function(canvas, pixelSize) {
|
|
||||||
this.context = canvas.getContext('2d');
|
|
||||||
this.canvas = canvas;
|
|
||||||
this.pixelSize = pixelSize || 1;
|
|
||||||
this.initImageData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Palette colors (RGB)
|
|
||||||
Screen.colors = [
|
|
||||||
[0xFF, 0xFF, 0xFF],
|
|
||||||
[0xAA, 0xAA, 0xAA],
|
|
||||||
[0x55, 0x55, 0x55],
|
|
||||||
[0x00, 0x00, 0x00]
|
|
||||||
];
|
|
||||||
|
|
||||||
Screen.physics = {
|
|
||||||
WIDTH : 160,
|
|
||||||
HEIGHT : 144,
|
|
||||||
FREQUENCY: 60
|
|
||||||
};
|
|
||||||
|
|
||||||
Screen.prototype.setPixelSize = function(pixelSize) {
|
|
||||||
this.pixelSize = pixelSize;
|
|
||||||
this.initImageData();
|
|
||||||
};
|
|
||||||
|
|
||||||
Screen.prototype.initImageData = function() {
|
|
||||||
this.canvas.width = Screen.physics.WIDTH * this.pixelSize;
|
|
||||||
this.canvas.height = Screen.physics.HEIGHT * this.pixelSize;
|
|
||||||
this.imageData = this.context.createImageData(this.canvas.width, this.canvas.height);
|
|
||||||
for (var i = 0; i < this.imageData.data.length; i++) {
|
|
||||||
this.imageData.data[i] = 255;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Screen.prototype.clearScreen = function() {
|
|
||||||
this.context.fillStyle = '#FFF';
|
|
||||||
this.context.fillRect(0, 0, Screen.physics.WIDTH * this.pixelSize, Screen.physics.HEIGHT * this.pixelSize);
|
|
||||||
};
|
|
||||||
|
|
||||||
Screen.prototype.fillImageData = function(buffer) {
|
|
||||||
for (var y = 0; y < Screen.physics.HEIGHT; y++) {
|
|
||||||
for (var py = 0; py < this.pixelSize; py++) {
|
|
||||||
var yOffset = (y * this.pixelSize + py) * this.canvas.width;
|
|
||||||
for (var x = 0; x < Screen.physics.WIDTH; x++) {
|
|
||||||
for (var px = 0; px < this.pixelSize; px++) {
|
|
||||||
var offset = yOffset + (x * this.pixelSize + px);
|
|
||||||
var v = Screen.colors[buffer[y * Screen.physics.WIDTH + x] | 0];
|
|
||||||
// set RGB values
|
|
||||||
this.imageData.data[offset * 4] = v[0];
|
|
||||||
this.imageData.data[offset * 4 + 1] = v[1];
|
|
||||||
this.imageData.data[offset * 4 + 2] = v[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Screen.prototype.render = function(buffer) {
|
|
||||||
this.fillImageData(buffer);
|
|
||||||
this.context.putImageData(this.imageData, 0, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.Screen = Screen;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,16 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// This exception should be thrown whenever a critical feature that
|
|
||||||
// has not been implemented is requested
|
|
||||||
function UnimplementedException(message, fatal) {
|
|
||||||
this.message = message;
|
|
||||||
this.name = UnimplementedException;
|
|
||||||
if (fatal === undefined) {
|
|
||||||
fatal = true;
|
|
||||||
}
|
|
||||||
this.fatal = fatal;
|
|
||||||
}
|
|
||||||
GameboyJS.UnimplementedException = UnimplementedException;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,50 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Object for mapping the cartridge RAM
|
|
||||||
var ExtRam = function() {
|
|
||||||
this.extRam = null;
|
|
||||||
this.ramSize = 0;
|
|
||||||
this.ramBank = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
ExtRam.prototype.loadRam = function(game, size) {
|
|
||||||
this.gameName = game;
|
|
||||||
|
|
||||||
this.ramSize = size;
|
|
||||||
this.ramBanksize = this.ramSize >= 0x2000 ? 8192 : 2048;
|
|
||||||
|
|
||||||
var key = this.getStorageKey();
|
|
||||||
var data = localStorage.getItem(key);
|
|
||||||
if (data == null) {
|
|
||||||
this.extRam = Array.apply(null, new Array(this.ramSize)).map(function(){return 0;});
|
|
||||||
} else {
|
|
||||||
this.extRam = JSON.parse(data);
|
|
||||||
if (this.extRam.length != size) {
|
|
||||||
console.error('Found RAM data but not matching expected size.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ExtRam.prototype.setRamBank = function(bank) {
|
|
||||||
this.ramBank = bank;
|
|
||||||
};
|
|
||||||
|
|
||||||
ExtRam.prototype.manageWrite = function(offset, value) {
|
|
||||||
this.extRam[this.ramBank * 8192 + offset] = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
ExtRam.prototype.manageRead = function(offset) {
|
|
||||||
return this.extRam[this.ramBank * 8192 + offset];
|
|
||||||
};
|
|
||||||
|
|
||||||
ExtRam.prototype.getStorageKey = function() {
|
|
||||||
return this.gameName + '_EXTRAM';;
|
|
||||||
};
|
|
||||||
// Actually save the RAM in the physical storage (localStorage)
|
|
||||||
ExtRam.prototype.saveRamData = function() {
|
|
||||||
localStorage.setItem(this.getStorageKey(), JSON.stringify(this.extRam));
|
|
||||||
};
|
|
||||||
GameboyJS.ExtRam = ExtRam;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,83 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// This is the default buttons mapping for the Gamepad
|
|
||||||
// It's optimized for the XBOX pad
|
|
||||||
//
|
|
||||||
// Any other mapping can be provided as a constructor argument of the Gamepad object
|
|
||||||
// An alternative mapping should be an object with keys being the indexes
|
|
||||||
// of the gamepad buttons and values the normalized gameboy button names
|
|
||||||
var xboxMapping = {
|
|
||||||
0: 'UP',
|
|
||||||
1: 'DOWN',
|
|
||||||
2: 'LEFT',
|
|
||||||
3: 'RIGHT',
|
|
||||||
4: 'START',
|
|
||||||
5: 'SELECT',
|
|
||||||
11: 'A',
|
|
||||||
12: 'B'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gamepad listener
|
|
||||||
// Communication layer between the Gamepad API and the Input class
|
|
||||||
// Any physical controller can be used but the mapping should be provided
|
|
||||||
// in order to get an optimal layout of the buttons (see above)
|
|
||||||
var Gamepad = function(mapping) {
|
|
||||||
this.gamepad = null;
|
|
||||||
this.state = {A:0,B:0,START:0,SELECT:0,LEFT:0,RIGHT:0,UP:0,DOWN:0};
|
|
||||||
this.pullInterval = null;
|
|
||||||
this.buttonMapping = mapping || xboxMapping;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize the keyboard listeners and set up the callbacks
|
|
||||||
// for button press / release
|
|
||||||
Gamepad.prototype.init = function(onPress, onRelease) {
|
|
||||||
this.onPress = onPress;
|
|
||||||
this.onRelease = onRelease;
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
window.addEventListener('gamepadconnected', function(e) {
|
|
||||||
self.gamepad = e.gamepad;
|
|
||||||
self.activatePull();
|
|
||||||
});
|
|
||||||
window.addEventListener('gamepaddisconnected', function(e) {
|
|
||||||
self.gamepad = null;
|
|
||||||
self.deactivatePull();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Gamepad.prototype.activatePull = function() {
|
|
||||||
this.deactivatePull();
|
|
||||||
this.pullInterval = setInterval(this.pullState.bind(this), 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
Gamepad.prototype.deactivatePull = function() {
|
|
||||||
clearInterval(this.pullInterval);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check the state of the current gamepad in order to detect any press/release action
|
|
||||||
Gamepad.prototype.pullState = function() {
|
|
||||||
for (var index in this.buttonMapping) {
|
|
||||||
var button = this.buttonMapping[index];
|
|
||||||
var oldState = this.state[button];
|
|
||||||
this.state[button] = this.gamepad.buttons[index].pressed;
|
|
||||||
|
|
||||||
if (this.state[button] == 1 && oldState == 0) {
|
|
||||||
this.managePress(button);
|
|
||||||
} else if (this.state[button] == 0 && oldState == 1) {
|
|
||||||
this.manageRelease(button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Gamepad.prototype.managePress = function(key) {
|
|
||||||
this.onPress(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
Gamepad.prototype.manageRelease = function(key) {
|
|
||||||
this.onRelease(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.Gamepad = Gamepad;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,57 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// The Input management system
|
|
||||||
//
|
|
||||||
// The pressKey() and releaseKey() functions should be called by a device class
|
|
||||||
// like GameboyJS.Keyboard after a physical button trigger event
|
|
||||||
//
|
|
||||||
// They rely on the name of the original buttons as parameters (see Input.keys)
|
|
||||||
var Input = function(cpu, pad) {
|
|
||||||
this.cpu = cpu;
|
|
||||||
this.memory = cpu.memory;
|
|
||||||
this.P1 = 0xFF00;
|
|
||||||
this.state = 0;
|
|
||||||
|
|
||||||
pad.init(this.pressKey.bind(this), this.releaseKey.bind(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
Input.keys = {
|
|
||||||
START: 0x80,
|
|
||||||
SELECT: 0x40,
|
|
||||||
B: 0x20,
|
|
||||||
A: 0x10,
|
|
||||||
DOWN: 0x08,
|
|
||||||
UP: 0x04,
|
|
||||||
LEFT: 0x02,
|
|
||||||
RIGHT: 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
Input.prototype.pressKey = function(key) {
|
|
||||||
this.state |= Input.keys[key];
|
|
||||||
|
|
||||||
this.cpu.requestInterrupt(GameboyJS.CPU.INTERRUPTS.HILO);
|
|
||||||
};
|
|
||||||
|
|
||||||
Input.prototype.releaseKey = function(key) {
|
|
||||||
var mask = 0xFF - Input.keys[key];
|
|
||||||
this.state &= mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
Input.prototype.update = function() {
|
|
||||||
var value = this.memory.rb(this.P1);
|
|
||||||
value = ((~value) & 0x30); // invert the value so 1 means 'active'
|
|
||||||
if (value & 0x10) { // direction keys listened
|
|
||||||
value |= (this.state & 0x0F);
|
|
||||||
} else if (value & 0x20) { // action keys listened
|
|
||||||
value |= ((this.state & 0xF0) >> 4);
|
|
||||||
} else if ((value & 0x30) == 0) { // no keys listened
|
|
||||||
value &= 0xF0;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = ((~value) & 0x3F); // invert back
|
|
||||||
this.memory[this.P1] = value;
|
|
||||||
};
|
|
||||||
GameboyJS.Input = Input;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,71 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Keyboard listener
|
|
||||||
// Does the mapping between the keyboard and the Input class
|
|
||||||
var Keyboard = function() {};
|
|
||||||
|
|
||||||
// Initialize the keyboard listeners and set up the callbacks
|
|
||||||
// for button press / release
|
|
||||||
Keyboard.prototype.init = function(onPress, onRelease) {
|
|
||||||
this.onPress = onPress;
|
|
||||||
this.onRelease = onRelease;
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
self.managePress(e.keyCode);
|
|
||||||
});
|
|
||||||
document.addEventListener('keyup', function(e) {
|
|
||||||
self.manageRelease(e.keyCode);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Keyboard.prototype.managePress = function(keycode) {
|
|
||||||
var key = this.translateKey(keycode);
|
|
||||||
if (key) {
|
|
||||||
this.onPress(key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Keyboard.prototype.manageRelease = function(keycode) {
|
|
||||||
var key = this.translateKey(keycode);
|
|
||||||
if (key) {
|
|
||||||
this.onRelease(key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Transform a keyboard keycode into a key of the Input.keys object
|
|
||||||
Keyboard.prototype.translateKey = function(keycode) {
|
|
||||||
var key = null;
|
|
||||||
switch (keycode) {
|
|
||||||
case 71: // G
|
|
||||||
key = 'A';
|
|
||||||
break;
|
|
||||||
case 66: // B
|
|
||||||
key = 'B';
|
|
||||||
break;
|
|
||||||
case 72: // H
|
|
||||||
key = 'START';
|
|
||||||
break;
|
|
||||||
case 78: // N
|
|
||||||
key = 'SELECT';
|
|
||||||
break;
|
|
||||||
case 37: // left
|
|
||||||
key = 'LEFT';
|
|
||||||
break;
|
|
||||||
case 38: // up
|
|
||||||
key = 'UP';
|
|
||||||
break;
|
|
||||||
case 39: // right
|
|
||||||
key = 'RIGHT';
|
|
||||||
break;
|
|
||||||
case 40: // down
|
|
||||||
key = 'DOWN';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
|
||||||
};
|
|
||||||
GameboyJS.Keyboard = Keyboard;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,186 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// List of CPU operations
|
|
||||||
// Most operations have been factorized here to limit code redundancy
|
|
||||||
//
|
|
||||||
// How to read operations:
|
|
||||||
// Uppercase letters qualify the kind of operation (LD = LOAD, INC = INCREMENT, etc.)
|
|
||||||
// Lowercase letters are used to hint parameters :
|
|
||||||
// r = register, n = 1 memory byte, sp = sp register,
|
|
||||||
// a = suffix for memory address, i = bit index
|
|
||||||
// Example : LDrrar = LOAD operation with two-registers memory address
|
|
||||||
// as first parameter and one register value as second
|
|
||||||
//
|
|
||||||
// Underscore-prefixed functions are here to delegate the logic between similar operations,
|
|
||||||
// they should not be called from outside
|
|
||||||
//
|
|
||||||
// It's up to each operation to update the CPU clock
|
|
||||||
var ops = {
|
|
||||||
LDrrnn: function(p, r1, r2) {p.wr(r2, p.memory.rb(p.r.pc));p.wr(r1, p.memory.rb(p.r.pc+1)); p.r.pc+=2;p.clock.c += 12;},
|
|
||||||
LDrrar: function(p, r1, r2, r3) {ops._LDav(p, GameboyJS.Util.getRegAddr(p, r1, r2), p.r[r3]);p.clock.c += 8;},
|
|
||||||
LDrrra: function(p, r1, r2, r3) {p.wr(r1, p.memory.rb(GameboyJS.Util.getRegAddr(p, r2, r3)));p.clock.c += 8;},
|
|
||||||
LDrn: function(p, r1) {p.wr(r1, p.memory.rb(p.r.pc++));p.clock.c += 8;},
|
|
||||||
LDrr: function(p, r1, r2) {p.wr(r1, p.r[r2]);p.clock.c += 4;},
|
|
||||||
LDrar: function(p, r1, r2) {p.memory.wb(p.r[r1]+0xFF00, p.r[r2]);p.clock.c += 8;},
|
|
||||||
LDrra: function(p, r1, r2) {p.wr(r1, p.memory.rb(p.r[r2]+0xFF00));p.clock.c += 8;},
|
|
||||||
LDspnn: function(p) {p.wr('sp', (p.memory.rb(p.r.pc + 1) << 8) + p.memory.rb(p.r.pc));p.r.pc+=2;p.clock.c += 12;},
|
|
||||||
LDsprr: function(p, r1, r2) {p.wr('sp', GameboyJS.Util.getRegAddr(p, r1, r2));p.clock.c += 8;},
|
|
||||||
LDnnar: function(p, r1) {var addr=(p.memory.rb(p.r.pc + 1) << 8) + p.memory.rb(p.r.pc);p.memory.wb(addr,p.r[r1]);p.r.pc+=2; p.clock.c += 16;},
|
|
||||||
LDrnna: function(p, r1) {var addr=(p.memory.rb(p.r.pc + 1) << 8) + p.memory.rb(p.r.pc);p.wr(r1, p.memory.rb(addr));p.r.pc+=2; p.clock.c += 16;},
|
|
||||||
LDrrspn:function(p, r1, r2) {var rel = p.memory.rb(p.r.pc++);rel=GameboyJS.Util.getSignedValue(rel);var val=p.r.sp + rel;
|
|
||||||
var c = (p.r.sp&0xFF) + (rel&0xFF) > 0xFF;var h = (p.r.sp & 0xF) + (rel & 0xF) > 0xF;val &= 0xFFFF;
|
|
||||||
var f = 0; if(h)f|=0x20;if(c)f|=0x10;p.wr('F', f);
|
|
||||||
p.wr(r1, val >> 8);p.wr(r2, val&0xFF);
|
|
||||||
p.clock.c+=12;},
|
|
||||||
LDnnsp: function(p) {var addr = p.memory.rb(p.r.pc++) + (p.memory.rb(p.r.pc++)<<8); ops._LDav(p, addr, p.r.sp & 0xFF);ops._LDav(p, addr+1, p.r.sp >> 8);p.clock.c+=20;},
|
|
||||||
LDrran: function(p, r1, r2){var addr = GameboyJS.Util.getRegAddr(p, r1, r2);ops._LDav(p, addr, p.memory.rb(p.r.pc++));p.clock.c+=12;},
|
|
||||||
_LDav: function(p, addr, val){p.memory.wb(addr, val);},
|
|
||||||
LDHnar: function(p, r1){p.memory.wb(0xFF00 + p.memory.rb(p.r.pc++), p.r[r1]);p.clock.c+=12;},
|
|
||||||
LDHrna: function(p, r1){p.wr(r1, p.memory.rb(0xFF00 + p.memory.rb(p.r.pc++)));p.clock.c+=12;},
|
|
||||||
INCrr: function(p, r1, r2) {p.wr(r2, (p.r[r2]+1)&0xFF); if (p.r[r2] == 0) p.wr(r1, (p.r[r1]+1)&0xFF);p.clock.c += 8;},
|
|
||||||
INCrra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var val = (p.memory.rb(addr)+1)&0xFF;var z = val==0;var h=(p.memory.rb(addr)&0xF)+1 > 0xF;
|
|
||||||
p.memory.wb(addr, val);
|
|
||||||
p.r.F&=0x10;if(h)p.r.F|=0x20;if(z)p.r.F|=0x80;
|
|
||||||
p.clock.c+=12;},
|
|
||||||
INCsp: function(p){p.wr('sp', p.r.sp+1); p.r.sp &= 0xFFFF; p.clock.c+=8;},
|
|
||||||
INCr: function(p, r1) {var h = ((p.r[r1]&0xF) + 1)&0x10;p.wr(r1, (p.r[r1] + 1)&0xFF);var z = p.r[r1]==0;
|
|
||||||
p.r.F&=0x10;if(h)p.r.F|=0x20;if(z)p.r.F|=0x80;
|
|
||||||
p.clock.c += 4;},
|
|
||||||
DECrr: function(p, r1, r2) {p.wr(r2, (p.r[r2] - 1) & 0xFF); if (p.r[r2] == 0xFF) p.wr(r1, (p.r[r1] - 1)&0xFF);p.clock.c += 8;},
|
|
||||||
DECsp: function(p){p.wr('sp', p.r.sp-1); p.r.sp &= 0xFFFF; p.clock.c+=8;},
|
|
||||||
DECr: function(p, r1) {var h = (p.r[r1]&0xF) < 1;p.wr(r1, (p.r[r1] - 1) & 0xFF);var z = p.r[r1]==0;
|
|
||||||
p.r.F&=0x10;p.r.F|=0x40;if(h)p.r.F|=0x20;if(z)p.r.F|=0x80;
|
|
||||||
p.clock.c += 4;},
|
|
||||||
DECrra: function(p, r1, r2){var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var val = (p.memory.rb(addr)-1)&0xFF;var z = val==0;var h=(p.memory.rb(addr)&0xF) < 1;
|
|
||||||
p.memory.wb(addr, val);
|
|
||||||
p.r.F&=0x10;p.r.F|=0x40;if(h)p.r.F|=0x20;if(z)p.r.F|=0x80;
|
|
||||||
p.clock.c+=12;},
|
|
||||||
ADDrr: function(p, r1, r2) {var n = p.r[r2];ops._ADDrn(p, r1, n); p.clock.c += 4;},
|
|
||||||
ADDrn: function(p, r1) {var n = p.memory.rb(p.r.pc++);ops._ADDrn(p, r1, n); p.clock.c+=8;},
|
|
||||||
_ADDrn: function(p, r1, n) {var h=((p.r[r1]&0xF)+(n&0xF))&0x10;p.wr(r1, p.r[r1]+n);var c=p.r[r1]&0x100;p.r[r1]&=0xFF;
|
|
||||||
var f = 0;if (p.r[r1]==0)f|=0x80;if (h)f|=0x20;if (c)f|=0x10;p.wr('F', f);},
|
|
||||||
ADDrrrr:function(p, r1, r2, r3, r4) {ops._ADDrrn(p, r1, r2, (p.r[r3]<<8) + p.r[r4]); p.clock.c+=8;},
|
|
||||||
ADDrrsp:function(p, r1, r2) {ops._ADDrrn(p, r1, r2, p.r.sp); p.clock.c += 8;},
|
|
||||||
ADDspn: function(p) {var v = p.memory.rb(p.r.pc++);v = GameboyJS.Util.getSignedValue(v);
|
|
||||||
var c = ((p.r.sp&0xFF) + (v&0xFF)) > 0xFF; var h = (p.r.sp & 0xF) + (v&0xF) > 0xF;
|
|
||||||
var f = 0; if(h)f|=0x20;if(c)f|=0x10;p.wr('F', f);
|
|
||||||
p.wr('sp', (p.r.sp + v) & 0xFFFF);
|
|
||||||
p.clock.c+=16;},
|
|
||||||
_ADDrrn:function(p, r1, r2, n) {var v1 = (p.r[r1]<<8) + p.r[r2];var v2 = n;
|
|
||||||
var res = v1 + v2;var c = res&0x10000;var h = ((v1&0xFFF) + (v2&0xFFF))&0x1000;var z = p.r.F&0x80;
|
|
||||||
res&=0xFFFF;p.r[r2]=res&0xFF;res=res>>8;p.r[r1]=res&0xFF;
|
|
||||||
var f=0;if(z)f|=0x80;if(h)f|=0x20;if(c)f|=0x10;p.r.F=f;},
|
|
||||||
ADCrr: function(p, r1, r2) {var n = p.r[r2]; ops._ADCrn(p, r1, n); p.clock.c += 4;},
|
|
||||||
ADCrn: function(p, r1) {var n = p.memory.rb(p.r.pc++); ops._ADCrn(p, r1, n); p.clock.c += 8;},
|
|
||||||
_ADCrn: function(p, r1, n) {
|
|
||||||
var c = p.r.F&0x10?1:0;var h=((p.r[r1]&0xF)+(n&0xF)+c)&0x10;
|
|
||||||
p.wr(r1, p.r[r1]+n+c);c=p.r[r1]&0x100;p.r[r1]&=0xFF;
|
|
||||||
var f = 0;if (p.r[r1]==0)f|=0x80;if (h)f|=0x20;if (c)f|=0x10;p.r.F=f;},
|
|
||||||
ADCrrra:function(p, r1, r2, r3) {var n = p.memory.rb(GameboyJS.Util.getRegAddr(p, r2, r3)); ops._ADCrn(p, r1, n); p.clock.c += 8;},
|
|
||||||
ADDrrra:function(p, r1, r2, r3) {var v = p.memory.rb(GameboyJS.Util.getRegAddr(p, r2, r3));var h=((p.r[r1]&0xF)+(v&0xF))&0x10;p.wr(r1, p.r[r1]+v);var c=p.r[r1]&0x100;p.r[r1]&=0xFF;
|
|
||||||
var f = 0;if (p.r[r1]==0)f|=0x80;if (h)f|=0x20;if (c)f|=0x10;p.wr('F', f);
|
|
||||||
p.clock.c += 8;},
|
|
||||||
SUBr: function(p, r1) {var n = p.r[r1];ops._SUBn(p, n);p.clock.c += 4;},
|
|
||||||
SUBn: function(p) {var n = p.memory.rb(p.r.pc++);ops._SUBn(p, n);p.clock.c += 8;},
|
|
||||||
SUBrra: function(p, r1, r2) {var n = p.memory.rb(GameboyJS.Util.getRegAddr(p, r1, r2));ops._SUBn(p, n);p.clock.c+=8;},
|
|
||||||
_SUBn: function(p, n) {var c = p.r.A < n;var h = (p.r.A&0xF) < (n&0xF);
|
|
||||||
p.wr('A', p.r.A - n);p.r.A&=0xFF; var z = p.r.A==0;
|
|
||||||
var f = 0x40;if (z)f|=0x80;if (h)f|=0x20;if (c)f|=0x10;p.wr('F', f);},
|
|
||||||
SBCn: function(p) {var n = p.memory.rb(p.r.pc++); ops._SBCn(p, n); p.clock.c += 8;},
|
|
||||||
SBCr: function(p, r1) {var n = p.r[r1]; ops._SBCn(p, n); p.clock.c += 4;},
|
|
||||||
SBCrra: function(p, r1, r2) {var v = p.memory.rb((p.r[r1] << 8) + p.r[r2]); ops._SBCn(p, v); p.clock.c += 8;},
|
|
||||||
_SBCn: function(p, n) {var carry = p.r.F&0x10 ? 1 : 0;
|
|
||||||
var c = p.r.A < n + carry;var h = (p.r.A&0xF) < (n&0xF) + carry;
|
|
||||||
p.wr('A', p.r.A - n - carry); p.r.A&=0xFF; var z = p.r.A == 0;
|
|
||||||
var f = 0x40;if (z)f|=0x80;if (h)f|=0x20;if (c)f|=0x10;p.r.F=f;},
|
|
||||||
ORr: function(p, r1) {p.r.A|=p.r[r1];p.r.F=(p.r.A==0)?0x80:0x00;p.clock.c += 4;},
|
|
||||||
ORn: function(p) {p.r.A|=p.memory.rb(p.r.pc++);p.r.F=(p.r.A==0)?0x80:0x00;p.clock.c += 8;},
|
|
||||||
ORrra: function(p, r1, r2) {p.r.A|=p.memory.rb((p.r[r1] << 8)+ p.r[r2]);p.r.F=(p.r.A==0)?0x80:0x00;p.clock.c += 8;},
|
|
||||||
ANDr: function(p, r1) {p.r.A&=p.r[r1];p.r.F=(p.r.A==0)?0xA0:0x20;p.clock.c += 4;},
|
|
||||||
ANDn: function(p) {p.r.A&=p.memory.rb(p.r.pc++);p.r.F=(p.r.A==0)?0xA0:0x20;p.clock.c += 8;},
|
|
||||||
ANDrra: function(p, r1, r2) {p.r.A&=p.memory.rb(GameboyJS.Util.getRegAddr(p, r1, r2));p.r.F=(p.r.A==0)?0xA0:0x20;p.clock.c += 8;},
|
|
||||||
XORr: function(p, r1) {p.r.A^=p.r[r1];p.r.F=(p.r.A==0)?0x80:0x00;p.clock.c += 4;},
|
|
||||||
XORn: function(p) {p.r.A^=p.memory.rb(p.r.pc++);p.r.F=(p.r.A==0)?0x80:0x00;p.clock.c += 8;},
|
|
||||||
XORrra: function(p, r1, r2) {p.r.A^=p.memory.rb((p.r[r1] << 8)+ p.r[r2]);p.r.F=(p.r.A==0)?0x80:0x00;p.clock.c += 8;},
|
|
||||||
CPr: function(p, r1) {var n = p.r[r1];ops._CPn(p, n); p.clock.c += 4;},
|
|
||||||
CPn: function(p) {var n =p.memory.rb(p.r.pc++);ops._CPn(p, n);p.clock.c+=8;},
|
|
||||||
CPrra: function(p, r1, r2) {var n = p.memory.rb(GameboyJS.Util.getRegAddr(p, r1, r2));ops._CPn(p, n);p.clock.c+=8;},
|
|
||||||
_CPn: function(p, n) {
|
|
||||||
var c = p.r.A < n;var z = p.r.A == n;var h = (p.r.A&0xF) < (n&0xF);
|
|
||||||
var f = 0x40;if(z)f+=0x80;if (h)f+=0x20;if (c)f+=0x10;p.r.F=f;},
|
|
||||||
RRCr: function(p, r1) {p.r.F=0;var out=p.r[r1] & 0x01;if(out)p.r.F|=0x10;p.r[r1]=(p.r[r1]>>1)|(out*0x80);if(p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
RRCrra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);p.r.F=0;var out=p.memory.rb(addr)&0x01;if(out)p.r.F|=0x10;p.memory.wb(addr, (p.memory.rb(addr)>>1)|(out*0x80));if(p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
RLCr: function(p, r1) {p.r.F=0;var out=p.r[r1]&0x80?1:0;if(out)p.r.F|=0x10;p.r[r1]=((p.r[r1]<<1)+out)&0xFF;if(p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
RLCrra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);p.r.F=0;var out=p.memory.rb(addr)&0x80?1:0;if(out)p.r.F|=0x10;p.memory.wb(addr, ((p.memory.rb(addr)<<1)+out)&0xFF);if(p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
RLr: function(p, r1) {var c=(p.r.F&0x10)?1:0;p.r.F=0;var out=p.r[r1]&0x80;out?p.r.F|=0x10:p.r.F&=0xEF;p.r[r1]=((p.r[r1]<<1)+c)&0xFF;if(p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
RLrra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var c=(p.r.F&0x10)?1:0;p.r.F=0;var out=p.memory.rb(addr)&0x80;out?p.r.F|=0x10:p.r.F&=0xEF;p.memory.wb(addr,((p.memory.rb(addr)<<1)+c)&0xFF);if(p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
RRr: function(p, r1) {var c=(p.r.F&0x10)?1:0;p.r.F=0;var out=p.r[r1]&0x01;out?p.r.F|=0x10:p.r.F&=0xEF;p.r[r1]=(p.r[r1]>>1)|(c*0x80);if(p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
RRrra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var c=(p.r.F&0x10)?1:0;p.r.F=0;var out=p.memory.rb(addr)&0x01;out?p.r.F|=0x10:p.r.F&=0xEF;p.memory.wb(addr,(p.memory.rb(addr)>>1)|(c*0x80));if(p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
SRAr: function(p, r1) {p.r.F = 0;if (p.r[r1]&0x01)p.r.F|=0x10;var msb=p.r[r1]&0x80;p.r[r1]=(p.r[r1]>>1)|msb;if (p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
SRArra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);p.r.F = 0;if (p.memory.rb(addr)&0x01)p.r.F|=0x10;var msb=p.memory.rb(addr)&0x80;p.memory.wb(addr, (p.memory.rb(addr)>>1)|msb);if (p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
SLAr: function(p, r1) {p.r.F = 0;if (p.r[r1]&0x80)p.r.F|=0x10;p.r[r1]=(p.r[r1]<<1)&0xFF;if (p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
SLArra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);p.r.F = 0;if (p.memory.rb(addr)&0x80)p.r.F|=0x10;p.memory.wb(addr, (p.memory.rb(addr)<<1)&0xFF);if (p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
SRLr: function(p, r1) {p.r.F = 0;if (p.r[r1]&0x01)p.r.F|=0x10;p.r[r1]=p.r[r1]>>1;if (p.r[r1]==0)p.r.F|=0x80;p.clock.c+=4;},
|
|
||||||
SRLrra: function(p, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);p.r.F = 0;if (p.memory.rb(addr)&0x01)p.r.F|=0x10;p.memory.wb(addr, p.memory.rb(addr)>>1);if (p.memory.rb(addr)==0)p.r.F|=0x80;p.clock.c+=12;},
|
|
||||||
BITir: function(p, i, r1) {var mask=1<<i;var z=(p.r[r1]&mask)?0:1;var f=p.r.F&0x10;f |= 0x20;if(z)f|=0x80;p.r.F=f;p.clock.c+=4;},
|
|
||||||
BITirra:function(p, i, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var mask=1<<i;var z=(p.memory.rb(addr)&mask)?0:1;var f=p.r.F&0x10;f |= 0x20;if(z)f|=0x80;p.r.F=f;p.clock.c+=8;},
|
|
||||||
SETir: function(p, i, r1) {var mask=1<<i;p.r[r1]|=mask;p.clock.c += 4;},
|
|
||||||
SETirra:function(p, i, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var mask=1<<i;p.memory.wb(addr, p.memory.rb(addr)|mask);p.clock.c += 12;},
|
|
||||||
RESir: function(p, i, r1) {var mask=0xFF - (1<<i);p.r[r1]&=mask;p.clock.c += 4;},
|
|
||||||
RESirra:function(p, i, r1, r2) {var addr = GameboyJS.Util.getRegAddr(p, r1, r2);var mask=0xFF - (1<<i);p.memory.wb(addr, p.memory.rb(addr)&mask);p.clock.c += 12;},
|
|
||||||
SWAPr: function(p, r1) {p.r[r1] = ops._SWAPn(p, p.r[r1]);p.clock.c+=4;},
|
|
||||||
SWAPrra:function(p, r1, r2){var addr = (p.r[r1] << 8)+ p.r[r2]; p.memory.wb(addr, ops._SWAPn(p, p.memory.rb(addr))); p.clock.c+=12;},
|
|
||||||
_SWAPn: function(p, n){p.r.F = n==0?0x80:0;return ((n&0xF0) >> 4) | ((n&0x0F) << 4);},
|
|
||||||
JPnn: function(p) {p.wr('pc', (p.memory.rb(p.r.pc+1) << 8) + p.memory.rb(p.r.pc));p.clock.c += 16;},
|
|
||||||
JRccn: function(p, cc) {if (GameboyJS.Util.testFlag(p, cc)){var v=p.memory.rb(p.r.pc++);v=GameboyJS.Util.getSignedValue(v);p.r.pc += v;p.clock.c+=4;}else{p.r.pc++;}p.clock.c += 8;},
|
|
||||||
JPccnn: function(p, cc) {if (GameboyJS.Util.testFlag(p, cc)){p.wr('pc', (p.memory.rb(p.r.pc+1) << 8) + p.memory.rb(p.r.pc));p.clock.c+=4;}else{p.r.pc+=2;}p.clock.c += 12;},
|
|
||||||
JPrr: function(p, r1, r2) {p.r.pc = (p.r[r1] << 8) + p.r[r2];p.clock.c += 4;},
|
|
||||||
JRn: function(p) {var v=p.memory.rb(p.r.pc++);v=GameboyJS.Util.getSignedValue(v);p.r.pc += v;p.clock.c += 12;},
|
|
||||||
PUSHrr: function(p, r1, r2) {p.wr('sp', p.r.sp-1);p.memory.wb(p.r.sp, p.r[r1]);p.wr('sp', p.r.sp-1);p.memory.wb(p.r.sp, p.r[r2]);p.clock.c+=16;},
|
|
||||||
POPrr: function(p, r1, r2) {p.wr(r2, p.memory.rb(p.r.sp));p.wr('sp', p.r.sp+1);p.wr(r1, p.memory.rb(p.r.sp));p.wr('sp', p.r.sp+1);p.clock.c+=12;},
|
|
||||||
RSTn: function(p, n) {p.wr('sp', p.r.sp-1);p.memory.wb(p.r.sp,p.r.pc>>8);p.wr('sp', p.r.sp-1);p.memory.wb(p.r.sp,p.r.pc&0xFF);p.r.pc=n;p.clock.c+=16;},
|
|
||||||
RET: function(p) {p.r.pc = p.memory.rb(p.r.sp);p.wr('sp', p.r.sp+1);p.r.pc+=p.memory.rb(p.r.sp)<<8;p.wr('sp', p.r.sp+1);p.clock.c += 16;},
|
|
||||||
RETcc: function(p, cc) {if (GameboyJS.Util.testFlag(p, cc)){p.r.pc = p.memory.rb(p.r.sp);p.wr('sp', p.r.sp+1);p.r.pc+=p.memory.rb(p.r.sp)<<8;p.wr('sp', p.r.sp+1);p.clock.c+=12;}p.clock.c+=8;},
|
|
||||||
CALLnn: function(p) {ops._CALLnn(p); p.clock.c+=24;},
|
|
||||||
CALLccnn:function(p, cc) {if (GameboyJS.Util.testFlag(p, cc)){ops._CALLnn(p);p.clock.c+=12;}else{p.r.pc+=2;}p.clock.c+=12; },
|
|
||||||
_CALLnn:function(p){p.wr('sp', p.r.sp - 1); p.memory.wb(p.r.sp, ((p.r.pc+2)&0xFF00)>>8);
|
|
||||||
p.wr('sp', p.r.sp - 1); p.memory.wb(p.r.sp, (p.r.pc+2)&0x00FF);
|
|
||||||
var j=p.memory.rb(p.r.pc)+(p.memory.rb(p.r.pc+1)<<8);p.r.pc=j;},
|
|
||||||
CPL: function(p) {p.wr('A', (~p.r.A)&0xFF);p.r.F|=0x60,p.clock.c += 4;},
|
|
||||||
CCF: function(p) {p.r.F&=0x9F;p.r.F&0x10?p.r.F&=0xE0:p.r.F|=0x10;p.clock.c += 4;},
|
|
||||||
SCF: function(p) {p.r.F&=0x9F;p.r.F|=0x10;p.clock.c+=4;},
|
|
||||||
DAA: function(p) {
|
|
||||||
var sub = (p.r.F&0x40) ? 1 : 0; var h = (p.r.F&0x20)?1:0;var c = (p.r.F&0x10)?1:0;
|
|
||||||
if (sub) {
|
|
||||||
if (h) {
|
|
||||||
p.r.A = (p.r.A - 0x6) & 0xFF;
|
|
||||||
}
|
|
||||||
if (c) {
|
|
||||||
p.r.A -= 0x60;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((p.r.A&0xF) > 9 || h) {
|
|
||||||
p.r.A += 0x6;
|
|
||||||
}
|
|
||||||
if (p.r.A > 0x9F || c) {
|
|
||||||
p.r.A += 0x60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p.r.A&0x100) c = 1;
|
|
||||||
|
|
||||||
p.r.A &= 0xFF;
|
|
||||||
p.r.F &= 0x40;if (p.r.A == 0) p.r.F|=0x80;if (c) p.r.F|=0x10;
|
|
||||||
p.clock.c += 4;
|
|
||||||
},
|
|
||||||
HALT: function(p) {p.halt(); p.clock.c+=4;},
|
|
||||||
DI: function(p) {p.disableInterrupts();p.clock.c += 4;},
|
|
||||||
EI: function(p) {p.enableInterrupts();p.clock.c += 4;},
|
|
||||||
RETI: function(p) {p.enableInterrupts();ops.RET(p);},
|
|
||||||
CB: function(p) {var opcode = p.memory.rb(p.r.pc++);
|
|
||||||
GameboyJS.opcodeCbmap[opcode](p);
|
|
||||||
p.clock.c+=4;}
|
|
||||||
};
|
|
||||||
GameboyJS.cpuOps = ops;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
123
src/main.js
123
src/main.js
|
@ -1,123 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var defaultOptions = {
|
|
||||||
pad: {class: GameboyJS.Keyboard, mapping: null},
|
|
||||||
zoom: 1,
|
|
||||||
romReaders: [],
|
|
||||||
statusContainerId: 'status',
|
|
||||||
gameNameContainerId: 'game-name',
|
|
||||||
errorContainerId: 'error'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gameboy class
|
|
||||||
//
|
|
||||||
// This object is the entry point of the application
|
|
||||||
// Will delegate user actions to the emulated devices
|
|
||||||
// and provide information where needed
|
|
||||||
var Gameboy = function(canvas, options) {
|
|
||||||
options = options || {};
|
|
||||||
this.options = GameboyJS.Util.extend({}, defaultOptions, options);
|
|
||||||
|
|
||||||
var cpu = new GameboyJS.CPU(this);
|
|
||||||
var screen = new GameboyJS.Screen(canvas, this.options.zoom);
|
|
||||||
var gpu = new GameboyJS.GPU(screen, cpu);
|
|
||||||
cpu.gpu = gpu;
|
|
||||||
|
|
||||||
var pad = new this.options.pad.class(this.options.pad.mapping);
|
|
||||||
var input = new GameboyJS.Input(cpu, pad);
|
|
||||||
cpu.input = input;
|
|
||||||
|
|
||||||
this.cpu = cpu;
|
|
||||||
this.screen = screen;
|
|
||||||
this.input = input;
|
|
||||||
this.pad = pad;
|
|
||||||
|
|
||||||
this.createRom(this.options.romReaders);
|
|
||||||
|
|
||||||
this.statusContainer = document.getElementById(this.options.statusContainerId) || document.createElement('div');
|
|
||||||
this.gameNameContainer = document.getElementById(this.options.gameNameContainerId) || document.createElement('div');
|
|
||||||
this.errorContainer = document.getElementById(this.options.errorContainerId) || document.createElement('div');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the ROM object and bind one or more readers
|
|
||||||
Gameboy.prototype.createRom = function (readers) {
|
|
||||||
var rom = new GameboyJS.Rom(this);
|
|
||||||
if (readers.length == 0) {
|
|
||||||
// add the default rom reader
|
|
||||||
var romReader = new GameboyJS.RomFileReader();
|
|
||||||
rom.addReader(romReader);
|
|
||||||
} else {
|
|
||||||
for (var i in readers) {
|
|
||||||
if (readers.hasOwnProperty(i)) {
|
|
||||||
rom.addReader(readers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Gameboy.prototype.startRom = function(rom) {
|
|
||||||
this.errorContainer.classList.add('hide');
|
|
||||||
this.cpu.reset();
|
|
||||||
try {
|
|
||||||
this.cpu.loadRom(rom.data);
|
|
||||||
this.setStatus('Game Running :');
|
|
||||||
this.setGameName(this.cpu.getGameName());
|
|
||||||
this.cpu.run();
|
|
||||||
} catch (e) {
|
|
||||||
this.handleException(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Gameboy.prototype.pause = function(value) {
|
|
||||||
if (value) {
|
|
||||||
this.setStatus('Game Paused :');
|
|
||||||
this.cpu.pause();
|
|
||||||
} else {
|
|
||||||
this.setStatus('Game Running :');
|
|
||||||
this.cpu.unpause();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Gameboy.prototype.error = function(message) {
|
|
||||||
this.setStatus('Error during execution');
|
|
||||||
this.setError('An error occurred during execution:' + message);
|
|
||||||
this.cpu.stop();
|
|
||||||
};
|
|
||||||
|
|
||||||
Gameboy.prototype.setStatus = function(status) {
|
|
||||||
this.statusContainer.innerHTML = status;
|
|
||||||
};
|
|
||||||
// Display an error message
|
|
||||||
Gameboy.prototype.setError = function(message) {
|
|
||||||
this.errorContainer.classList.remove('hide');
|
|
||||||
this.errorContainer.innerHTML = message;
|
|
||||||
};
|
|
||||||
// Display the name of the game running
|
|
||||||
Gameboy.prototype.setGameName = function(name) {
|
|
||||||
this.gameNameContainer.innerHTML = name;
|
|
||||||
};
|
|
||||||
Gameboy.prototype.setSoundEnabled = function(value) {
|
|
||||||
if (value) {
|
|
||||||
this.cpu.apu.connect();
|
|
||||||
} else {
|
|
||||||
this.cpu.apu.disconnect();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Gameboy.prototype.setScreenZoom = function(value) {
|
|
||||||
this.screen.setPixelSize(value);
|
|
||||||
};
|
|
||||||
Gameboy.prototype.handleException = function(e) {
|
|
||||||
if (e instanceof GameboyJS.UnimplementedException) {
|
|
||||||
if (e.fatal) {
|
|
||||||
this.error('This cartridge is not supported ('+ e.message +')');
|
|
||||||
} else {
|
|
||||||
console.error(e.message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
GameboyJS.Gameboy = Gameboy;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
134
src/mbc.js
134
src/mbc.js
|
@ -1,134 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Memory bank controllers
|
|
||||||
|
|
||||||
var MBC = {};
|
|
||||||
|
|
||||||
// Create an MBC instance depending on the type specified in the cartridge
|
|
||||||
MBC.getMbcInstance = function(memory, type) {
|
|
||||||
var instance;
|
|
||||||
switch (type) {
|
|
||||||
case 0x00:
|
|
||||||
instance = new MBC0(memory);
|
|
||||||
break;
|
|
||||||
case 0x01: case 0x02: case 0x03:
|
|
||||||
instance = new MBC1(memory);
|
|
||||||
break;
|
|
||||||
case 0x0F: case 0x10: case 0x11: case 0x12: case 0x13:
|
|
||||||
instance = new MBC3(memory);
|
|
||||||
break;
|
|
||||||
case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E:
|
|
||||||
instance = new MBC5(memory);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new GameboyJS.UnimplementedException('MBC type not supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
var MBC1 = function(memory) {
|
|
||||||
this.memory = memory;
|
|
||||||
this.romBankNumber = 1;
|
|
||||||
this.mode = 0; // mode 0 = ROM, mode 1 = RAM
|
|
||||||
this.ramEnabled = true;
|
|
||||||
this.extRam = new GameboyJS.ExtRam();
|
|
||||||
};
|
|
||||||
|
|
||||||
MBC1.prototype.loadRam = function(game, size) {
|
|
||||||
this.extRam.loadRam(game, size);
|
|
||||||
};
|
|
||||||
|
|
||||||
MBC1.prototype.manageWrite = function(addr, value) {
|
|
||||||
switch (addr & 0xF000) {
|
|
||||||
case 0x0000: case 0x1000: // enable RAM
|
|
||||||
this.ramEnabled = (value & 0x0A) ? true : false;
|
|
||||||
if (this.ramEnabled) {
|
|
||||||
this.extRam.saveRamData();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x2000: case 0x3000: // ROM bank number lower 5 bits
|
|
||||||
value &= 0x1F;
|
|
||||||
if (value == 0) value = 1;
|
|
||||||
var mask = this.mode ? 0 : 0xE0;
|
|
||||||
this.romBankNumber = (this.romBankNumber & mask) +value;
|
|
||||||
this.memory.loadRomBank(this.romBankNumber);
|
|
||||||
break;
|
|
||||||
case 0x4000: case 0x5000: // RAM bank or high bits ROM
|
|
||||||
value &= 0x03;
|
|
||||||
if (this.mode == 0) { // ROM upper bits
|
|
||||||
this.romBankNumber = (this.romBankNumber&0x1F) | (value << 5);
|
|
||||||
this.memory.loadRomBank(this.romBankNumber);
|
|
||||||
} else { // RAM bank
|
|
||||||
this.extRam.setRamBank(value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x6000: case 0x7000: // ROM / RAM mode
|
|
||||||
this.mode = value & 1;
|
|
||||||
break;
|
|
||||||
case 0xA000: case 0xB000:
|
|
||||||
this.extRam.manageWrite(addr - 0xA000, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MBC1.prototype.readRam = function(addr) {
|
|
||||||
return this.extRam.manageRead(addr - 0xA000);
|
|
||||||
};
|
|
||||||
|
|
||||||
var MBC3 = function(memory) {
|
|
||||||
this.memory = memory;
|
|
||||||
this.romBankNumber = 1;
|
|
||||||
this.ramEnabled = true;
|
|
||||||
this.extRam = new GameboyJS.ExtRam();
|
|
||||||
};
|
|
||||||
|
|
||||||
MBC3.prototype.loadRam = function(game, size) {
|
|
||||||
this.extRam.loadRam(game, size);
|
|
||||||
};
|
|
||||||
|
|
||||||
MBC3.prototype.manageWrite = function(addr, value) {
|
|
||||||
switch (addr & 0xF000) {
|
|
||||||
case 0x0000: case 0x1000: // enable RAM
|
|
||||||
this.ramEnabled = (value & 0x0A) ? true : false;
|
|
||||||
if (this.ramEnabled) {
|
|
||||||
this.extRam.saveRamData();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x2000: case 0x3000: // ROM bank number
|
|
||||||
value &= 0x7F;
|
|
||||||
if (value == 0) value = 1;
|
|
||||||
this.romBankNumber = value;
|
|
||||||
this.memory.loadRomBank(this.romBankNumber);
|
|
||||||
break;
|
|
||||||
case 0x4000: case 0x5000: // RAM bank
|
|
||||||
this.extRam.setRamBank(value);
|
|
||||||
break;
|
|
||||||
case 0x6000: case 0x7000: // Latch clock data
|
|
||||||
throw new GameboyJS.UnimplementedException('cartridge clock not supported', false);
|
|
||||||
break;
|
|
||||||
case 0xA000: case 0xB000:
|
|
||||||
this.extRam.manageWrite(addr - 0xA000, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MBC3.prototype.readRam = function(addr) {
|
|
||||||
return this.extRam.manageRead(addr - 0xA000);
|
|
||||||
};
|
|
||||||
|
|
||||||
// declare MBC5 for compatibility with most cartriges
|
|
||||||
// does not support rumble feature
|
|
||||||
var MBC5 = MBC3;
|
|
||||||
|
|
||||||
// MBC0 exists for consistency and manages the no-MBC cartriges
|
|
||||||
var MBC0 = function(memory) {this.memory = memory;};
|
|
||||||
|
|
||||||
MBC0.prototype.manageWrite = function(addr, value) {
|
|
||||||
this.memory.loadRomBank(value);
|
|
||||||
};
|
|
||||||
MBC0.prototype.readRam = function(addr) {return 0;};
|
|
||||||
MBC0.prototype.loadRam = function() {};
|
|
||||||
|
|
||||||
GameboyJS.MBC = MBC;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
153
src/memory.js
153
src/memory.js
|
@ -1,153 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Memory unit
|
|
||||||
var Memory = function(cpu) {
|
|
||||||
this.MEM_SIZE = 65536; // 64KB
|
|
||||||
|
|
||||||
this.MBCtype = 0;
|
|
||||||
this.banksize = 0x4000;
|
|
||||||
this.rom = null;
|
|
||||||
this.mbc = null;
|
|
||||||
this.cpu = cpu;
|
|
||||||
};
|
|
||||||
|
|
||||||
Memory.addresses = {
|
|
||||||
VRAM_START : 0x8000,
|
|
||||||
VRAM_END : 0x9FFF,
|
|
||||||
|
|
||||||
EXTRAM_START : 0xA000,
|
|
||||||
EXTRAM_END : 0xBFFF,
|
|
||||||
|
|
||||||
OAM_START : 0xFE00,
|
|
||||||
OAM_END : 0xFE9F,
|
|
||||||
|
|
||||||
DEVICE_START: 0xFF00,
|
|
||||||
DEVICE_END: 0xFF7F
|
|
||||||
};
|
|
||||||
|
|
||||||
// Memory can be accessed as an Array
|
|
||||||
Memory.prototype = new Array();
|
|
||||||
|
|
||||||
Memory.prototype.reset = function() {
|
|
||||||
this.length = this.MEM_SIZE;
|
|
||||||
for (var i = Memory.addresses.VRAM_START; i <= Memory.addresses.VRAM_END; i++) {
|
|
||||||
this[i] = 0;
|
|
||||||
}
|
|
||||||
for (var i = Memory.addresses.DEVICE_START; i <= Memory.addresses.DEVICE_END; i++) {
|
|
||||||
this[i] = 0;
|
|
||||||
}
|
|
||||||
this[0xFFFF] = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Memory.prototype.setRomData = function(data) {
|
|
||||||
this.rom = data;
|
|
||||||
this.loadRomBank(0);
|
|
||||||
this.mbc = GameboyJS.MBC.getMbcInstance(this, this[0x147]);
|
|
||||||
this.loadRomBank(1);
|
|
||||||
this.mbc.loadRam(this.cpu.getGameName(), this.cpu.getRamSize());
|
|
||||||
};
|
|
||||||
|
|
||||||
Memory.prototype.loadRomBank = function(index) {
|
|
||||||
var start = index ? 0x4000 : 0x0;
|
|
||||||
var romStart = index * 0x4000;
|
|
||||||
for (var i = 0; i < this.banksize; i++) {
|
|
||||||
this[i + start] = this.rom[romStart + i];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Video ram accessor
|
|
||||||
Memory.prototype.vram = function(address) {
|
|
||||||
if (address < Memory.addresses.VRAM_START || address > Memory.addresses.VRAM_END) {
|
|
||||||
throw 'VRAM access in out of bounds address ' + address;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this[address];
|
|
||||||
};
|
|
||||||
|
|
||||||
// OAM ram accessor
|
|
||||||
Memory.prototype.oamram = function(address) {
|
|
||||||
if (address < Memory.addresses.OAM_START || address > Memory.addresses.OAM_END) {
|
|
||||||
throw 'OAMRAM access in out of bounds address ' + address;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this[address];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Device ram accessor
|
|
||||||
Memory.prototype.deviceram = function(address, value) {
|
|
||||||
if (address < Memory.addresses.DEVICERAM_START || address > Memory.addresses.DEVICERAM_END) {
|
|
||||||
throw 'Device RAM access in out of bounds address ' + address;
|
|
||||||
}
|
|
||||||
if (typeof value === "undefined") {
|
|
||||||
return this[address];
|
|
||||||
} else {
|
|
||||||
this[address] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Memory read proxy function
|
|
||||||
// Used to centralize memory read access
|
|
||||||
Memory.prototype.rb = function (addr) {
|
|
||||||
if (addr >= 0xFF10 && addr < 0xFF40) {
|
|
||||||
var mask = apuMask[addr - 0xFF10];
|
|
||||||
return this[addr] | mask;
|
|
||||||
}
|
|
||||||
if ((addr >= 0xA000 && addr < 0xC000)) {
|
|
||||||
return this.mbc.readRam(addr);
|
|
||||||
}
|
|
||||||
return this[addr];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Bitmasks for audio addresses reads
|
|
||||||
var apuMask = [
|
|
||||||
0x80,0x3F,0x00,0xFF,0xBF, // NR10-NR15
|
|
||||||
0xFF,0x3F,0x00,0xFF,0xBF, // NR20-NR25
|
|
||||||
0x7F,0xFF,0x9F,0xFF,0xBF, // NR30-NR35
|
|
||||||
0xFF,0xFF,0x00,0x00,0xBF, // NR40-NR45
|
|
||||||
0x00,0x00,0x70, // NR50-NR52
|
|
||||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Wave RAM
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
|
||||||
];
|
|
||||||
|
|
||||||
// Memory write proxy function
|
|
||||||
// Used to centralize memory writes and delegate specific behaviour
|
|
||||||
// to the correct units
|
|
||||||
Memory.prototype.wb = function(addr, value) {
|
|
||||||
if (addr < 0x8000 || (addr >= 0xA000 && addr < 0xC000)) { // MBC
|
|
||||||
this.mbc.manageWrite(addr, value);
|
|
||||||
} else if (addr >= 0xFF10 && addr <= 0xFF3F) { // sound registers
|
|
||||||
this.cpu.apu.manageWrite(addr, value);
|
|
||||||
} else if (addr == 0xFF00) { // input register
|
|
||||||
this[addr] = ((this[addr] & 0x0F) | (value & 0x30));
|
|
||||||
} else {
|
|
||||||
this[addr] = value;
|
|
||||||
if ((addr & 0xFF00) == 0xFF00) {
|
|
||||||
if (addr == 0xFF02) {
|
|
||||||
if (value & 0x80) {
|
|
||||||
this.cpu.enableSerialTransfer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (addr == 0xFF04) {
|
|
||||||
this.cpu.resetDivTimer();
|
|
||||||
}
|
|
||||||
if (addr == 0xFF46) { // OAM DMA transfer
|
|
||||||
this.dmaTransfer(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a DMA transfer (OAM data from cartrige to RAM)
|
|
||||||
Memory.prototype.dmaTransfer = function(startAddressPrefix) {
|
|
||||||
var startAddress = (startAddressPrefix << 8);
|
|
||||||
for (var i = 0; i < 0xA0; i++) {
|
|
||||||
this[Memory.addresses.OAM_START + i] = this[startAddress + i];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.Memory = Memory;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
559
src/opcodes.js
559
src/opcodes.js
|
@ -1,559 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var ops = GameboyJS.cpuOps;
|
|
||||||
// Each opcode (0 to 0xFF) is associated to a CPU operation
|
|
||||||
// CPU operations are implemented separately
|
|
||||||
// The cbmap object holds operations for CB prefixed opcodes (0xCB00 to 0xCBFF)
|
|
||||||
// Non existent opcodes are commented out and marked empty
|
|
||||||
var map = {
|
|
||||||
0x00: function(p){p.clock.c += 4;},
|
|
||||||
0x01: function(p){ops.LDrrnn(p, 'B', 'C');},
|
|
||||||
0x02: function(p){ops.LDrrar(p, 'B', 'C', 'A');},
|
|
||||||
0x03: function(p){ops.INCrr(p, 'B', 'C');},
|
|
||||||
0x04: function(p){ops.INCr(p, 'B');},
|
|
||||||
0x05: function(p){ops.DECr(p, 'B');},
|
|
||||||
0x06: function(p){ops.LDrn(p, 'B');},
|
|
||||||
0x07: function(p){var out=p.r.A & 0x80?1:0; out ? p.r.F=0x10:p.r.F=0; p.wr('A', ((p.r.A<<1)+out)&0xFF);p.clock.c+=4;},
|
|
||||||
0x08: function(p){ops.LDnnsp(p);},
|
|
||||||
0x09: function(p){ops.ADDrrrr(p, 'H', 'L', 'B', 'C');},
|
|
||||||
0x0A: function(p){ops.LDrrra(p, 'A', 'B', 'C');},
|
|
||||||
0x0B: function(p){ops.DECrr(p, 'B', 'C');},
|
|
||||||
0x0C: function(p){ops.INCr(p, 'C');},
|
|
||||||
0x0D: function(p){ops.DECr(p, 'C');},
|
|
||||||
0x0E: function(p){ops.LDrn(p, 'C');},
|
|
||||||
0x0F: function(p){var out=p.r.A & 0x01; out ? p.r.F=0x10:p.r.F=0; p.wr('A', (p.r.A>>1)|(out*0x80));p.clock.c+=4;},
|
|
||||||
|
|
||||||
0x10: function(p){p.r.pc++;p.clock.c+=4;},
|
|
||||||
0x11: function(p){ops.LDrrnn(p, 'D', 'E');},
|
|
||||||
0x12: function(p){ops.LDrrar(p, 'D', 'E', 'A');},
|
|
||||||
0x13: function(p){ops.INCrr(p, 'D', 'E');},
|
|
||||||
0x14: function(p){ops.INCr(p, 'D');},
|
|
||||||
0x15: function(p){ops.DECr(p, 'D');},
|
|
||||||
0x16: function(p){ops.LDrn(p, 'D');},
|
|
||||||
0x17: function(p){var c = (p.r.F&0x10)?1:0;var out=p.r.A & 0x80?1:0; out ? p.r.F=0x10:p.r.F=0; p.wr('A',((p.r.A<<1)+c)&0xFF);p.clock.c+=4;},
|
|
||||||
0x18: function(p){ops.JRn(p);},
|
|
||||||
0x19: function(p){ops.ADDrrrr(p, 'H', 'L', 'D', 'E');},
|
|
||||||
0x1A: function(p){ops.LDrrra(p, 'A', 'D', 'E');},
|
|
||||||
0x1B: function(p){ops.DECrr(p, 'D', 'E');},
|
|
||||||
0x1C: function(p){ops.INCr(p, 'E');},
|
|
||||||
0x1D: function(p){ops.DECr(p, 'E');},
|
|
||||||
0x1E: function(p){ops.LDrn(p, 'E');},
|
|
||||||
0x1F: function(p){var c = (p.r.F&0x10)?1:0;var out=p.r.A & 0x01; out ? p.r.F=0x10:p.r.F=0; p.wr('A', (p.r.A>>1)|(c*0x80));p.clock.c+=4;},
|
|
||||||
|
|
||||||
0x20: function(p){ops.JRccn(p, 'NZ');},
|
|
||||||
0x21: function(p){ops.LDrrnn(p, 'H', 'L');},
|
|
||||||
0x22: function(p){ops.LDrrar(p, 'H', 'L', 'A');ops.INCrr(p, 'H', 'L');p.clock.c -= 8;},
|
|
||||||
0x23: function(p){ops.INCrr(p, 'H', 'L');},
|
|
||||||
0x24: function(p){ops.INCr(p, 'H');},
|
|
||||||
0x25: function(p){ops.DECr(p, 'H');},
|
|
||||||
0x26: function(p){ops.LDrn(p, 'H');},
|
|
||||||
0x27: function(p){ops.DAA(p);},
|
|
||||||
0x28: function(p){ops.JRccn(p, 'Z');},
|
|
||||||
0x29: function(p){ops.ADDrrrr(p, 'H', 'L', 'H', 'L');},
|
|
||||||
0x2A: function(p){ops.LDrrra(p, 'A', 'H', 'L');ops.INCrr(p, 'H', 'L');p.clock.c -= 8;},
|
|
||||||
0x2B: function(p){ops.DECrr(p, 'H', 'L');},
|
|
||||||
0x2C: function(p){ops.INCr(p, 'L');},
|
|
||||||
0x2D: function(p){ops.DECr(p, 'L');},
|
|
||||||
0x2E: function(p){ops.LDrn(p, 'L');},
|
|
||||||
0x2F: function(p){ops.CPL(p);},
|
|
||||||
|
|
||||||
0x30: function(p){ops.JRccn(p, 'NC');},
|
|
||||||
0x31: function(p){ops.LDspnn(p);},
|
|
||||||
0x32: function(p){ops.LDrrar(p, 'H', 'L', 'A');ops.DECrr(p, 'H', 'L');p.clock.c -= 8;},
|
|
||||||
0x33: function(p){ops.INCsp(p);},
|
|
||||||
0x34: function(p){ops.INCrra(p, 'H', 'L');},
|
|
||||||
0x35: function(p){ops.DECrra(p, 'H', 'L');},
|
|
||||||
0x36: function(p){ops.LDrran(p, 'H', 'L');},
|
|
||||||
0x37: function(p){ops.SCF(p);},
|
|
||||||
0x38: function(p){ops.JRccn(p, 'C');},
|
|
||||||
0x39: function(p){ops.ADDrrsp(p, 'H', 'L');},
|
|
||||||
0x3A: function(p){ops.LDrrra(p, 'A', 'H', 'L');ops.DECrr(p, 'H', 'L');p.clock.c -= 8;},
|
|
||||||
0x3B: function(p){ops.DECsp(p);},
|
|
||||||
0x3C: function(p){ops.INCr(p, 'A');},
|
|
||||||
0x3D: function(p){ops.DECr(p, 'A');},
|
|
||||||
0x3E: function(p){ops.LDrn(p, 'A');},
|
|
||||||
0x3F: function(p){ops.CCF(p);},
|
|
||||||
|
|
||||||
0x40: function(p){ops.LDrr(p, 'B', 'B');},
|
|
||||||
0x41: function(p){ops.LDrr(p, 'B', 'C');},
|
|
||||||
0x42: function(p){ops.LDrr(p, 'B', 'D');},
|
|
||||||
0x43: function(p){ops.LDrr(p, 'B', 'E');},
|
|
||||||
0x44: function(p){ops.LDrr(p, 'B', 'H');},
|
|
||||||
0x45: function(p){ops.LDrr(p, 'B', 'L');},
|
|
||||||
0x46: function(p){ops.LDrrra(p, 'B', 'H', 'L');},
|
|
||||||
0x47: function(p){ops.LDrr(p, 'B', 'A');},
|
|
||||||
0x48: function(p){ops.LDrr(p, 'C', 'B');},
|
|
||||||
0x49: function(p){ops.LDrr(p, 'C', 'C');},
|
|
||||||
0x4A: function(p){ops.LDrr(p, 'C', 'D');},
|
|
||||||
0x4B: function(p){ops.LDrr(p, 'C', 'E');},
|
|
||||||
0x4C: function(p){ops.LDrr(p, 'C', 'H');},
|
|
||||||
0x4D: function(p){ops.LDrr(p, 'C', 'L');},
|
|
||||||
0x4E: function(p){ops.LDrrra(p, 'C', 'H', 'L');},
|
|
||||||
0x4F: function(p){ops.LDrr(p, 'C', 'A');},
|
|
||||||
|
|
||||||
0x50: function(p){ops.LDrr(p, 'D', 'B');},
|
|
||||||
0x51: function(p){ops.LDrr(p, 'D', 'C');},
|
|
||||||
0x52: function(p){ops.LDrr(p, 'D', 'D');},
|
|
||||||
0x53: function(p){ops.LDrr(p, 'D', 'E');},
|
|
||||||
0x54: function(p){ops.LDrr(p, 'D', 'H');},
|
|
||||||
0x55: function(p){ops.LDrr(p, 'D', 'L');},
|
|
||||||
0x56: function(p){ops.LDrrra(p, 'D', 'H', 'L');},
|
|
||||||
0x57: function(p){ops.LDrr(p, 'D', 'A');},
|
|
||||||
0x58: function(p){ops.LDrr(p, 'E', 'B');},
|
|
||||||
0x59: function(p){ops.LDrr(p, 'E', 'C');},
|
|
||||||
0x5A: function(p){ops.LDrr(p, 'E', 'D');},
|
|
||||||
0x5B: function(p){ops.LDrr(p, 'E', 'E');},
|
|
||||||
0x5C: function(p){ops.LDrr(p, 'E', 'H');},
|
|
||||||
0x5D: function(p){ops.LDrr(p, 'E', 'L');},
|
|
||||||
0x5E: function(p){ops.LDrrra(p, 'E', 'H', 'L');},
|
|
||||||
0x5F: function(p){ops.LDrr(p, 'E', 'A');},
|
|
||||||
|
|
||||||
0x60: function(p){ops.LDrr(p, 'H', 'B');},
|
|
||||||
0x61: function(p){ops.LDrr(p, 'H', 'C');},
|
|
||||||
0x62: function(p){ops.LDrr(p, 'H', 'D');},
|
|
||||||
0x63: function(p){ops.LDrr(p, 'H', 'E');},
|
|
||||||
0x64: function(p){ops.LDrr(p, 'H', 'H');},
|
|
||||||
0x65: function(p){ops.LDrr(p, 'H', 'L');},
|
|
||||||
0x66: function(p){ops.LDrrra(p, 'H', 'H', 'L');},
|
|
||||||
0x67: function(p){ops.LDrr(p, 'H', 'A');},
|
|
||||||
0x68: function(p){ops.LDrr(p, 'L', 'B');},
|
|
||||||
0x69: function(p){ops.LDrr(p, 'L', 'C');},
|
|
||||||
0x6A: function(p){ops.LDrr(p, 'L', 'D');},
|
|
||||||
0x6B: function(p){ops.LDrr(p, 'L', 'E');},
|
|
||||||
0x6C: function(p){ops.LDrr(p, 'L', 'H');},
|
|
||||||
0x6D: function(p){ops.LDrr(p, 'L', 'L');},
|
|
||||||
0x6E: function(p){ops.LDrrra(p, 'L', 'H', 'L');},
|
|
||||||
0x6F: function(p){ops.LDrr(p, 'L', 'A');},
|
|
||||||
|
|
||||||
0x70: function(p){ops.LDrrar(p, 'H', 'L', 'B');},
|
|
||||||
0x71: function(p){ops.LDrrar(p, 'H', 'L', 'C');},
|
|
||||||
0x72: function(p){ops.LDrrar(p, 'H', 'L', 'D');},
|
|
||||||
0x73: function(p){ops.LDrrar(p, 'H', 'L', 'E');},
|
|
||||||
0x74: function(p){ops.LDrrar(p, 'H', 'L', 'H');},
|
|
||||||
0x75: function(p){ops.LDrrar(p, 'H', 'L', 'L');},
|
|
||||||
0x76: function(p){ops.HALT(p);},
|
|
||||||
0x77: function(p){ops.LDrrar(p, 'H', 'L', 'A');},
|
|
||||||
0x78: function(p){ops.LDrr(p, 'A', 'B');},
|
|
||||||
0x79: function(p){ops.LDrr(p, 'A', 'C');},
|
|
||||||
0x7A: function(p){ops.LDrr(p, 'A', 'D');},
|
|
||||||
0x7B: function(p){ops.LDrr(p, 'A', 'E');},
|
|
||||||
0x7C: function(p){ops.LDrr(p, 'A', 'H');},
|
|
||||||
0x7D: function(p){ops.LDrr(p, 'A', 'L');},
|
|
||||||
0x7E: function(p){ops.LDrrra(p, 'A', 'H', 'L');},
|
|
||||||
0x7F: function(p){ops.LDrr(p, 'A', 'A');},
|
|
||||||
|
|
||||||
0x80: function(p){ops.ADDrr(p, 'A', 'B');},
|
|
||||||
0x81: function(p){ops.ADDrr(p, 'A', 'C');},
|
|
||||||
0x82: function(p){ops.ADDrr(p, 'A', 'D');},
|
|
||||||
0x83: function(p){ops.ADDrr(p, 'A', 'E');},
|
|
||||||
0x84: function(p){ops.ADDrr(p, 'A', 'H');},
|
|
||||||
0x85: function(p){ops.ADDrr(p, 'A', 'L');},
|
|
||||||
0x86: function(p){ops.ADDrrra(p, 'A', 'H', 'L');},
|
|
||||||
0x87: function(p){ops.ADDrr(p, 'A', 'A');},
|
|
||||||
0x88: function(p){ops.ADCrr(p, 'A', 'B');},
|
|
||||||
0x89: function(p){ops.ADCrr(p, 'A', 'C');},
|
|
||||||
0x8A: function(p){ops.ADCrr(p, 'A', 'D');},
|
|
||||||
0x8B: function(p){ops.ADCrr(p, 'A', 'E');},
|
|
||||||
0x8C: function(p){ops.ADCrr(p, 'A', 'H');},
|
|
||||||
0x8D: function(p){ops.ADCrr(p, 'A', 'L');},
|
|
||||||
0x8E: function(p){ops.ADCrrra(p, 'A', 'H', 'L');},
|
|
||||||
0x8F: function(p){ops.ADCrr(p, 'A', 'A');},
|
|
||||||
|
|
||||||
0x90: function(p){ops.SUBr(p, 'B');},
|
|
||||||
0x91: function(p){ops.SUBr(p, 'C');},
|
|
||||||
0x92: function(p){ops.SUBr(p, 'D');},
|
|
||||||
0x93: function(p){ops.SUBr(p, 'E');},
|
|
||||||
0x94: function(p){ops.SUBr(p, 'H');},
|
|
||||||
0x95: function(p){ops.SUBr(p, 'L');},
|
|
||||||
0x96: function(p){ops.SUBrra(p, 'H', 'L');},
|
|
||||||
0x97: function(p){ops.SUBr(p, 'A');},
|
|
||||||
0x98: function(p){ops.SBCr(p, 'B');},
|
|
||||||
0x99: function(p){ops.SBCr(p, 'C');},
|
|
||||||
0x9A: function(p){ops.SBCr(p, 'D');},
|
|
||||||
0x9B: function(p){ops.SBCr(p, 'E');},
|
|
||||||
0x9C: function(p){ops.SBCr(p, 'H');},
|
|
||||||
0x9D: function(p){ops.SBCr(p, 'L');},
|
|
||||||
0x9E: function(p){ops.SBCrra(p, 'H', 'L');},
|
|
||||||
0x9F: function(p){ops.SBCr(p, 'A');},
|
|
||||||
|
|
||||||
0xA0: function(p){ops.ANDr(p, 'B');},
|
|
||||||
0xA1: function(p){ops.ANDr(p, 'C');},
|
|
||||||
0xA2: function(p){ops.ANDr(p, 'D');},
|
|
||||||
0xA3: function(p){ops.ANDr(p, 'E');},
|
|
||||||
0xA4: function(p){ops.ANDr(p, 'H');},
|
|
||||||
0xA5: function(p){ops.ANDr(p, 'L');},
|
|
||||||
0xA6: function(p){ops.ANDrra(p, 'H', 'L');},
|
|
||||||
0xA7: function(p){ops.ANDr(p, 'A');},
|
|
||||||
0xA8: function(p){ops.XORr(p, 'B');},
|
|
||||||
0xA9: function(p){ops.XORr(p, 'C');},
|
|
||||||
0xAA: function(p){ops.XORr(p, 'D');},
|
|
||||||
0xAB: function(p){ops.XORr(p, 'E');},
|
|
||||||
0xAC: function(p){ops.XORr(p, 'H');},
|
|
||||||
0xAD: function(p){ops.XORr(p, 'L');},
|
|
||||||
0xAE: function(p){ops.XORrra(p, 'H', 'L');},
|
|
||||||
0xAF: function(p){ops.XORr(p, 'A');},
|
|
||||||
|
|
||||||
0xB0: function(p){ops.ORr(p, 'B');},
|
|
||||||
0xB1: function(p){ops.ORr(p, 'C');},
|
|
||||||
0xB2: function(p){ops.ORr(p, 'D');},
|
|
||||||
0xB3: function(p){ops.ORr(p, 'E');},
|
|
||||||
0xB4: function(p){ops.ORr(p, 'H');},
|
|
||||||
0xB5: function(p){ops.ORr(p, 'L');},
|
|
||||||
0xB6: function(p){ops.ORrra(p, 'H', 'L');},
|
|
||||||
0xB7: function(p){ops.ORr(p, 'A');},
|
|
||||||
0xB8: function(p){ops.CPr(p, 'B');},
|
|
||||||
0xB9: function(p){ops.CPr(p, 'C');},
|
|
||||||
0xBA: function(p){ops.CPr(p, 'D');},
|
|
||||||
0xBB: function(p){ops.CPr(p, 'E');},
|
|
||||||
0xBC: function(p){ops.CPr(p, 'H');},
|
|
||||||
0xBD: function(p){ops.CPr(p, 'L');},
|
|
||||||
0xBE: function(p){ops.CPrra(p, 'H', 'L');},
|
|
||||||
0xBF: function(p){ops.CPr(p, 'A');},
|
|
||||||
|
|
||||||
0xC0: function(p){ops.RETcc(p, 'NZ');},
|
|
||||||
0xC1: function(p){ops.POPrr(p, 'B', 'C');},
|
|
||||||
0xC2: function(p){ops.JPccnn(p, 'NZ');},
|
|
||||||
0xC3: function(p){ops.JPnn(p);},
|
|
||||||
0xC4: function(p){ops.CALLccnn(p, 'NZ');},
|
|
||||||
0xC5: function(p){ops.PUSHrr(p, 'B', 'C');},
|
|
||||||
0xC6: function(p){ops.ADDrn(p, 'A');},
|
|
||||||
0xC7: function(p){ops.RSTn(p, 0x00);},
|
|
||||||
0xC8: function(p){ops.RETcc(p, 'Z');},
|
|
||||||
0xC9: function(p){ops.RET(p);},
|
|
||||||
0xCA: function(p){ops.JPccnn(p, 'Z');},
|
|
||||||
0xCB: function(p){ops.CB(p);},
|
|
||||||
0xCC: function(p){ops.CALLccnn(p, 'Z');},
|
|
||||||
0xCD: function(p){ops.CALLnn(p);},
|
|
||||||
0xCE: function(p){ops.ADCrn(p, 'A');},
|
|
||||||
0xCF: function(p){ops.RSTn(p, 0x08);},
|
|
||||||
|
|
||||||
0xD0: function(p){ops.RETcc(p, 'NC');},
|
|
||||||
0xD1: function(p){ops.POPrr(p, 'D', 'E');},
|
|
||||||
0xD2: function(p){ops.JPccnn(p, 'NC');},
|
|
||||||
//0xD3 empty
|
|
||||||
0xD4: function(p){ops.CALLccnn(p, 'NC');},
|
|
||||||
0xD5: function(p){ops.PUSHrr(p, 'D', 'E');},
|
|
||||||
0xD6: function(p){ops.SUBn(p);},
|
|
||||||
0xD7: function(p){ops.RSTn(p, 0x10);},
|
|
||||||
0xD8: function(p){ops.RETcc(p, 'C');},
|
|
||||||
0xD9: function(p){ops.RETI(p);},
|
|
||||||
0xDA: function(p){ops.JPccnn(p, 'C');},
|
|
||||||
//0xDB empty
|
|
||||||
0xDC: function(p){ops.CALLccnn(p, 'C');},
|
|
||||||
//0xDD empty
|
|
||||||
0xDE: function(p){ops.SBCn(p);},
|
|
||||||
0xDF: function(p){ops.RSTn(p, 0x18);},
|
|
||||||
|
|
||||||
0xE0: function(p){ops.LDHnar(p, 'A');},
|
|
||||||
0xE1: function(p){ops.POPrr(p, 'H', 'L');},
|
|
||||||
0xE2: function(p){ops.LDrar(p, 'C', 'A');},
|
|
||||||
//0xE3 empty
|
|
||||||
//0xE4 empty
|
|
||||||
0xE5: function(p){ops.PUSHrr(p, 'H', 'L');},
|
|
||||||
0xE6: function(p){ops.ANDn(p);},
|
|
||||||
0xE7: function(p){ops.RSTn(p, 0x20);},
|
|
||||||
0xE8: function(p){ops.ADDspn(p);},
|
|
||||||
0xE9: function(p){ops.JPrr(p, 'H', 'L');},
|
|
||||||
0xEA: function(p){ops.LDnnar(p, 'A');},
|
|
||||||
//0xEB empty
|
|
||||||
//0xEC empty
|
|
||||||
//0xED empty
|
|
||||||
0xEE: function(p){ops.XORn(p);},
|
|
||||||
0xEF: function(p){ops.RSTn(p, 0x28);},
|
|
||||||
|
|
||||||
0xF0: function(p){ops.LDHrna(p, 'A');},
|
|
||||||
0xF1: function(p){ops.POPrr(p, 'A', 'F');},
|
|
||||||
0xF2: function(p){ops.LDrra(p, 'A', 'C');},
|
|
||||||
0xF3: function(p){ops.DI(p);},
|
|
||||||
//0xF4 empty
|
|
||||||
0xF5: function(p){ops.PUSHrr(p, 'A', 'F');},
|
|
||||||
0xF6: function(p){ops.ORn(p);},
|
|
||||||
0xF7: function(p){ops.RSTn(p, 0x30);},
|
|
||||||
0xF8: function(p){ops.LDrrspn(p, 'H', 'L');},
|
|
||||||
0xF9: function(p){ops.LDsprr(p, 'H', 'L');},
|
|
||||||
0xFA: function(p){ops.LDrnna(p, 'A');},
|
|
||||||
0xFB: function(p){ops.EI(p);},
|
|
||||||
//0xFC empty
|
|
||||||
//0xFD empty
|
|
||||||
0xFE: function(p){ops.CPn(p);},
|
|
||||||
0xFF: function(p){ops.RSTn(p, 0x38);}
|
|
||||||
};
|
|
||||||
|
|
||||||
var cbmap = {
|
|
||||||
0x00: function(p){ops.RLCr(p, 'B');},
|
|
||||||
0x01: function(p){ops.RLCr(p, 'C');},
|
|
||||||
0x02: function(p){ops.RLCr(p, 'D');},
|
|
||||||
0x03: function(p){ops.RLCr(p, 'E');},
|
|
||||||
0x04: function(p){ops.RLCr(p, 'H');},
|
|
||||||
0x05: function(p){ops.RLCr(p, 'L');},
|
|
||||||
0x06: function(p){ops.RLCrra(p, 'H', 'L');},
|
|
||||||
0x07: function(p){ops.RLCr(p, 'A');},
|
|
||||||
0x08: function(p){ops.RRCr(p, 'B');},
|
|
||||||
0x09: function(p){ops.RRCr(p, 'C');},
|
|
||||||
0x0A: function(p){ops.RRCr(p, 'D');},
|
|
||||||
0x0B: function(p){ops.RRCr(p, 'E');},
|
|
||||||
0x0C: function(p){ops.RRCr(p, 'H');},
|
|
||||||
0x0D: function(p){ops.RRCr(p, 'L');},
|
|
||||||
0x0E: function(p){ops.RRCrra(p, 'H', 'L');},
|
|
||||||
0x0F: function(p){ops.RRCr(p, 'A');},
|
|
||||||
|
|
||||||
0x10: function(p){ops.RLr(p, 'B');},
|
|
||||||
0x11: function(p){ops.RLr(p, 'C');},
|
|
||||||
0x12: function(p){ops.RLr(p, 'D');},
|
|
||||||
0x13: function(p){ops.RLr(p, 'E');},
|
|
||||||
0x14: function(p){ops.RLr(p, 'H');},
|
|
||||||
0x15: function(p){ops.RLr(p, 'L');},
|
|
||||||
0x16: function(p){ops.RLrra(p, 'H', 'L');},
|
|
||||||
0x17: function(p){ops.RLr(p, 'A');},
|
|
||||||
0x18: function(p){ops.RRr(p, 'B');},
|
|
||||||
0x19: function(p){ops.RRr(p, 'C');},
|
|
||||||
0x1A: function(p){ops.RRr(p, 'D');},
|
|
||||||
0x1B: function(p){ops.RRr(p, 'E');},
|
|
||||||
0x1C: function(p){ops.RRr(p, 'H');},
|
|
||||||
0x1D: function(p){ops.RRr(p, 'L');},
|
|
||||||
0x1E: function(p){ops.RRrra(p, 'H', 'L');},
|
|
||||||
0x1F: function(p){ops.RRr(p, 'A');},
|
|
||||||
|
|
||||||
0x20: function(p){ops.SLAr(p, 'B');},
|
|
||||||
0x21: function(p){ops.SLAr(p, 'C');},
|
|
||||||
0x22: function(p){ops.SLAr(p, 'D');},
|
|
||||||
0x23: function(p){ops.SLAr(p, 'E');},
|
|
||||||
0x24: function(p){ops.SLAr(p, 'H');},
|
|
||||||
0x25: function(p){ops.SLAr(p, 'L');},
|
|
||||||
0x26: function(p){ops.SLArra(p, 'H', 'L');},
|
|
||||||
0x27: function(p){ops.SLAr(p, 'A');},
|
|
||||||
0x28: function(p){ops.SRAr(p, 'B');},
|
|
||||||
0x29: function(p){ops.SRAr(p, 'C');},
|
|
||||||
0x2A: function(p){ops.SRAr(p, 'D');},
|
|
||||||
0x2B: function(p){ops.SRAr(p, 'E');},
|
|
||||||
0x2C: function(p){ops.SRAr(p, 'H');},
|
|
||||||
0x2D: function(p){ops.SRAr(p, 'L');},
|
|
||||||
0x2E: function(p){ops.SRArra(p, 'H', 'L');},
|
|
||||||
0x2F: function(p){ops.SRAr(p, 'A');},
|
|
||||||
|
|
||||||
0x30: function(p){ops.SWAPr(p, 'B');},
|
|
||||||
0x31: function(p){ops.SWAPr(p, 'C');},
|
|
||||||
0x32: function(p){ops.SWAPr(p, 'D');},
|
|
||||||
0x33: function(p){ops.SWAPr(p, 'E');},
|
|
||||||
0x34: function(p){ops.SWAPr(p, 'H');},
|
|
||||||
0x35: function(p){ops.SWAPr(p, 'L');},
|
|
||||||
0x36: function(p){ops.SWAPrra(p, 'H', 'L');},
|
|
||||||
0x37: function(p){ops.SWAPr(p, 'A');},
|
|
||||||
0x38: function(p){ops.SRLr(p, 'B');},
|
|
||||||
0x39: function(p){ops.SRLr(p, 'C');},
|
|
||||||
0x3A: function(p){ops.SRLr(p, 'D');},
|
|
||||||
0x3B: function(p){ops.SRLr(p, 'E');},
|
|
||||||
0x3C: function(p){ops.SRLr(p, 'H');},
|
|
||||||
0x3D: function(p){ops.SRLr(p, 'L');},
|
|
||||||
0x3E: function(p){ops.SRLrra(p, 'H', 'L');},
|
|
||||||
0x3F: function(p){ops.SRLr(p, 'A');},
|
|
||||||
|
|
||||||
0x40: function(p){ops.BITir(p, 0, 'B');},
|
|
||||||
0x41: function(p){ops.BITir(p, 0, 'C');},
|
|
||||||
0x42: function(p){ops.BITir(p, 0, 'D');},
|
|
||||||
0x43: function(p){ops.BITir(p, 0, 'E');},
|
|
||||||
0x44: function(p){ops.BITir(p, 0, 'H');},
|
|
||||||
0x45: function(p){ops.BITir(p, 0, 'L');},
|
|
||||||
0x46: function(p){ops.BITirra(p, 0, 'H', 'L');},
|
|
||||||
0x47: function(p){ops.BITir(p, 0, 'A');},
|
|
||||||
0x48: function(p){ops.BITir(p, 1, 'B');},
|
|
||||||
0x49: function(p){ops.BITir(p, 1, 'C');},
|
|
||||||
0x4A: function(p){ops.BITir(p, 1, 'D');},
|
|
||||||
0x4B: function(p){ops.BITir(p, 1, 'E');},
|
|
||||||
0x4C: function(p){ops.BITir(p, 1, 'H');},
|
|
||||||
0x4D: function(p){ops.BITir(p, 1, 'L');},
|
|
||||||
0x4E: function(p){ops.BITirra(p, 1, 'H', 'L');},
|
|
||||||
0x4F: function(p){ops.BITir(p, 1, 'A');},
|
|
||||||
|
|
||||||
0x50: function(p){ops.BITir(p, 2, 'B');},
|
|
||||||
0x51: function(p){ops.BITir(p, 2, 'C');},
|
|
||||||
0x52: function(p){ops.BITir(p, 2, 'D');},
|
|
||||||
0x53: function(p){ops.BITir(p, 2, 'E');},
|
|
||||||
0x54: function(p){ops.BITir(p, 2, 'H');},
|
|
||||||
0x55: function(p){ops.BITir(p, 2, 'L');},
|
|
||||||
0x56: function(p){ops.BITirra(p, 2, 'H', 'L');},
|
|
||||||
0x57: function(p){ops.BITir(p, 2, 'A');},
|
|
||||||
0x58: function(p){ops.BITir(p, 3, 'B');},
|
|
||||||
0x59: function(p){ops.BITir(p, 3, 'C');},
|
|
||||||
0x5A: function(p){ops.BITir(p, 3, 'D');},
|
|
||||||
0x5B: function(p){ops.BITir(p, 3, 'E');},
|
|
||||||
0x5C: function(p){ops.BITir(p, 3, 'H');},
|
|
||||||
0x5D: function(p){ops.BITir(p, 3, 'L');},
|
|
||||||
0x5E: function(p){ops.BITirra(p, 3, 'H', 'L');},
|
|
||||||
0x5F: function(p){ops.BITir(p, 3, 'A');},
|
|
||||||
|
|
||||||
0x60: function(p){ops.BITir(p, 4, 'B');},
|
|
||||||
0x61: function(p){ops.BITir(p, 4, 'C');},
|
|
||||||
0x62: function(p){ops.BITir(p, 4, 'D');},
|
|
||||||
0x63: function(p){ops.BITir(p, 4, 'E');},
|
|
||||||
0x64: function(p){ops.BITir(p, 4, 'H');},
|
|
||||||
0x65: function(p){ops.BITir(p, 4, 'L');},
|
|
||||||
0x66: function(p){ops.BITirra(p, 4, 'H', 'L');},
|
|
||||||
0x67: function(p){ops.BITir(p, 4, 'A');},
|
|
||||||
0x68: function(p){ops.BITir(p, 5, 'B');},
|
|
||||||
0x69: function(p){ops.BITir(p, 5, 'C');},
|
|
||||||
0x6A: function(p){ops.BITir(p, 5, 'D');},
|
|
||||||
0x6B: function(p){ops.BITir(p, 5, 'E');},
|
|
||||||
0x6C: function(p){ops.BITir(p, 5, 'H');},
|
|
||||||
0x6D: function(p){ops.BITir(p, 5, 'L');},
|
|
||||||
0x6E: function(p){ops.BITirra(p, 5, 'H', 'L');},
|
|
||||||
0x6F: function(p){ops.BITir(p, 5, 'A');},
|
|
||||||
|
|
||||||
0x70: function(p){ops.BITir(p, 6, 'B');},
|
|
||||||
0x71: function(p){ops.BITir(p, 6, 'C');},
|
|
||||||
0x72: function(p){ops.BITir(p, 6, 'D');},
|
|
||||||
0x73: function(p){ops.BITir(p, 6, 'E');},
|
|
||||||
0x74: function(p){ops.BITir(p, 6, 'H');},
|
|
||||||
0x75: function(p){ops.BITir(p, 6, 'L');},
|
|
||||||
0x76: function(p){ops.BITirra(p, 6, 'H', 'L');},
|
|
||||||
0x77: function(p){ops.BITir(p, 6, 'A');},
|
|
||||||
0x78: function(p){ops.BITir(p, 7, 'B');},
|
|
||||||
0x79: function(p){ops.BITir(p, 7, 'C');},
|
|
||||||
0x7A: function(p){ops.BITir(p, 7, 'D');},
|
|
||||||
0x7B: function(p){ops.BITir(p, 7, 'E');},
|
|
||||||
0x7C: function(p){ops.BITir(p, 7, 'H');},
|
|
||||||
0x7D: function(p){ops.BITir(p, 7, 'L');},
|
|
||||||
0x7E: function(p){ops.BITirra(p, 7, 'H', 'L');},
|
|
||||||
0x7F: function(p){ops.BITir(p, 7, 'A');},
|
|
||||||
|
|
||||||
0x80: function(p){ops.RESir(p, 0, 'B');},
|
|
||||||
0x81: function(p){ops.RESir(p, 0, 'C');},
|
|
||||||
0x82: function(p){ops.RESir(p, 0, 'D');},
|
|
||||||
0x83: function(p){ops.RESir(p, 0, 'E');},
|
|
||||||
0x84: function(p){ops.RESir(p, 0, 'H');},
|
|
||||||
0x85: function(p){ops.RESir(p, 0, 'L');},
|
|
||||||
0x86: function(p){ops.RESirra(p, 0, 'H', 'L');},
|
|
||||||
0x87: function(p){ops.RESir(p, 0, 'A');},
|
|
||||||
0x88: function(p){ops.RESir(p, 1, 'B');},
|
|
||||||
0x89: function(p){ops.RESir(p, 1, 'C');},
|
|
||||||
0x8A: function(p){ops.RESir(p, 1, 'D');},
|
|
||||||
0x8B: function(p){ops.RESir(p, 1, 'E');},
|
|
||||||
0x8C: function(p){ops.RESir(p, 1, 'H');},
|
|
||||||
0x8D: function(p){ops.RESir(p, 1, 'L');},
|
|
||||||
0x8E: function(p){ops.RESirra(p, 1, 'H', 'L');},
|
|
||||||
0x8F: function(p){ops.RESir(p, 1, 'A');},
|
|
||||||
|
|
||||||
0x90: function(p){ops.RESir(p, 2, 'B');},
|
|
||||||
0x91: function(p){ops.RESir(p, 2, 'C');},
|
|
||||||
0x92: function(p){ops.RESir(p, 2, 'D');},
|
|
||||||
0x93: function(p){ops.RESir(p, 2, 'E');},
|
|
||||||
0x94: function(p){ops.RESir(p, 2, 'H');},
|
|
||||||
0x95: function(p){ops.RESir(p, 2, 'L');},
|
|
||||||
0x96: function(p){ops.RESirra(p, 2, 'H', 'L');},
|
|
||||||
0x97: function(p){ops.RESir(p, 2, 'A');},
|
|
||||||
0x98: function(p){ops.RESir(p, 3, 'B');},
|
|
||||||
0x99: function(p){ops.RESir(p, 3, 'C');},
|
|
||||||
0x9A: function(p){ops.RESir(p, 3, 'D');},
|
|
||||||
0x9B: function(p){ops.RESir(p, 3, 'E');},
|
|
||||||
0x9C: function(p){ops.RESir(p, 3, 'H');},
|
|
||||||
0x9D: function(p){ops.RESir(p, 3, 'L');},
|
|
||||||
0x9E: function(p){ops.RESirra(p, 3, 'H', 'L');},
|
|
||||||
0x9F: function(p){ops.RESir(p, 3, 'A');},
|
|
||||||
|
|
||||||
0xA0: function(p){ops.RESir(p, 4, 'B');},
|
|
||||||
0xA1: function(p){ops.RESir(p, 4, 'C');},
|
|
||||||
0xA2: function(p){ops.RESir(p, 4, 'D');},
|
|
||||||
0xA3: function(p){ops.RESir(p, 4, 'E');},
|
|
||||||
0xA4: function(p){ops.RESir(p, 4, 'H');},
|
|
||||||
0xA5: function(p){ops.RESir(p, 4, 'L');},
|
|
||||||
0xA6: function(p){ops.RESirra(p, 4, 'H', 'L');},
|
|
||||||
0xA7: function(p){ops.RESir(p, 4, 'A');},
|
|
||||||
0xA8: function(p){ops.RESir(p, 5, 'B');},
|
|
||||||
0xA9: function(p){ops.RESir(p, 5, 'C');},
|
|
||||||
0xAA: function(p){ops.RESir(p, 5, 'D');},
|
|
||||||
0xAB: function(p){ops.RESir(p, 5, 'E');},
|
|
||||||
0xAC: function(p){ops.RESir(p, 5, 'H');},
|
|
||||||
0xAD: function(p){ops.RESir(p, 5, 'L');},
|
|
||||||
0xAE: function(p){ops.RESirra(p, 5, 'H', 'L');},
|
|
||||||
0xAF: function(p){ops.RESir(p, 5, 'A');},
|
|
||||||
|
|
||||||
0xB0: function(p){ops.RESir(p, 6, 'B');},
|
|
||||||
0xB1: function(p){ops.RESir(p, 6, 'C');},
|
|
||||||
0xB2: function(p){ops.RESir(p, 6, 'D');},
|
|
||||||
0xB3: function(p){ops.RESir(p, 6, 'E');},
|
|
||||||
0xB4: function(p){ops.RESir(p, 6, 'H');},
|
|
||||||
0xB5: function(p){ops.RESir(p, 6, 'L');},
|
|
||||||
0xB6: function(p){ops.RESirra(p, 6, 'H', 'L');},
|
|
||||||
0xB7: function(p){ops.RESir(p, 6, 'A');},
|
|
||||||
0xB8: function(p){ops.RESir(p, 7, 'B');},
|
|
||||||
0xB9: function(p){ops.RESir(p, 7, 'C');},
|
|
||||||
0xBA: function(p){ops.RESir(p, 7, 'D');},
|
|
||||||
0xBB: function(p){ops.RESir(p, 7, 'E');},
|
|
||||||
0xBC: function(p){ops.RESir(p, 7, 'H');},
|
|
||||||
0xBD: function(p){ops.RESir(p, 7, 'L');},
|
|
||||||
0xBE: function(p){ops.RESirra(p, 7, 'H', 'L');},
|
|
||||||
0xBF: function(p){ops.RESir(p, 7, 'A');},
|
|
||||||
|
|
||||||
0xC0: function(p){ops.SETir(p, 0, 'B');},
|
|
||||||
0xC1: function(p){ops.SETir(p, 0, 'C');},
|
|
||||||
0xC2: function(p){ops.SETir(p, 0, 'D');},
|
|
||||||
0xC3: function(p){ops.SETir(p, 0, 'E');},
|
|
||||||
0xC4: function(p){ops.SETir(p, 0, 'H');},
|
|
||||||
0xC5: function(p){ops.SETir(p, 0, 'L');},
|
|
||||||
0xC6: function(p){ops.SETirra(p, 0, 'H', 'L');},
|
|
||||||
0xC7: function(p){ops.SETir(p, 0, 'A');},
|
|
||||||
0xC8: function(p){ops.SETir(p, 1, 'B');},
|
|
||||||
0xC9: function(p){ops.SETir(p, 1, 'C');},
|
|
||||||
0xCA: function(p){ops.SETir(p, 1, 'D');},
|
|
||||||
0xCB: function(p){ops.SETir(p, 1, 'E');},
|
|
||||||
0xCC: function(p){ops.SETir(p, 1, 'H');},
|
|
||||||
0xCD: function(p){ops.SETir(p, 1, 'L');},
|
|
||||||
0xCE: function(p){ops.SETirra(p, 1, 'H', 'L');},
|
|
||||||
0xCF: function(p){ops.SETir(p, 1, 'A');},
|
|
||||||
|
|
||||||
0xD0: function(p){ops.SETir(p, 2, 'B');},
|
|
||||||
0xD1: function(p){ops.SETir(p, 2, 'C');},
|
|
||||||
0xD2: function(p){ops.SETir(p, 2, 'D');},
|
|
||||||
0xD3: function(p){ops.SETir(p, 2, 'E');},
|
|
||||||
0xD4: function(p){ops.SETir(p, 2, 'H');},
|
|
||||||
0xD5: function(p){ops.SETir(p, 2, 'L');},
|
|
||||||
0xD6: function(p){ops.SETirra(p, 2, 'H', 'L');},
|
|
||||||
0xD7: function(p){ops.SETir(p, 2, 'A');},
|
|
||||||
0xD8: function(p){ops.SETir(p, 3, 'B');},
|
|
||||||
0xD9: function(p){ops.SETir(p, 3, 'C');},
|
|
||||||
0xDA: function(p){ops.SETir(p, 3, 'D');},
|
|
||||||
0xDB: function(p){ops.SETir(p, 3, 'E');},
|
|
||||||
0xDC: function(p){ops.SETir(p, 3, 'H');},
|
|
||||||
0xDD: function(p){ops.SETir(p, 3, 'L');},
|
|
||||||
0xDE: function(p){ops.SETirra(p, 3, 'H', 'L');},
|
|
||||||
0xDF: function(p){ops.SETir(p, 3, 'A');},
|
|
||||||
|
|
||||||
0xE0: function(p){ops.SETir(p, 4, 'B');},
|
|
||||||
0xE1: function(p){ops.SETir(p, 4, 'C');},
|
|
||||||
0xE2: function(p){ops.SETir(p, 4, 'D');},
|
|
||||||
0xE3: function(p){ops.SETir(p, 4, 'E');},
|
|
||||||
0xE4: function(p){ops.SETir(p, 4, 'H');},
|
|
||||||
0xE5: function(p){ops.SETir(p, 4, 'L');},
|
|
||||||
0xE6: function(p){ops.SETirra(p, 4, 'H', 'L');},
|
|
||||||
0xE7: function(p){ops.SETir(p, 4, 'A');},
|
|
||||||
0xE8: function(p){ops.SETir(p, 5, 'B');},
|
|
||||||
0xE9: function(p){ops.SETir(p, 5, 'C');},
|
|
||||||
0xEA: function(p){ops.SETir(p, 5, 'D');},
|
|
||||||
0xEB: function(p){ops.SETir(p, 5, 'E');},
|
|
||||||
0xEC: function(p){ops.SETir(p, 5, 'H');},
|
|
||||||
0xED: function(p){ops.SETir(p, 5, 'L');},
|
|
||||||
0xEE: function(p){ops.SETirra(p, 5, 'H', 'L');},
|
|
||||||
0xEF: function(p){ops.SETir(p, 5, 'A');},
|
|
||||||
|
|
||||||
0xF0: function(p){ops.SETir(p, 6, 'B');},
|
|
||||||
0xF1: function(p){ops.SETir(p, 6, 'C');},
|
|
||||||
0xF2: function(p){ops.SETir(p, 6, 'D');},
|
|
||||||
0xF3: function(p){ops.SETir(p, 6, 'E');},
|
|
||||||
0xF4: function(p){ops.SETir(p, 6, 'H');},
|
|
||||||
0xF5: function(p){ops.SETir(p, 6, 'L');},
|
|
||||||
0xF6: function(p){ops.SETirra(p, 6, 'H', 'L');},
|
|
||||||
0xF7: function(p){ops.SETir(p, 6, 'A');},
|
|
||||||
0xF8: function(p){ops.SETir(p, 7, 'B');},
|
|
||||||
0xF9: function(p){ops.SETir(p, 7, 'C');},
|
|
||||||
0xFA: function(p){ops.SETir(p, 7, 'D');},
|
|
||||||
0xFB: function(p){ops.SETir(p, 7, 'E');},
|
|
||||||
0xFC: function(p){ops.SETir(p, 7, 'H');},
|
|
||||||
0xFD: function(p){ops.SETir(p, 7, 'L');},
|
|
||||||
0xFE: function(p){ops.SETirra(p, 7, 'H', 'L');},
|
|
||||||
0xFF: function(p){ops.SETir(p, 7, 'A');}
|
|
||||||
};
|
|
||||||
GameboyJS.opcodeMap = map;
|
|
||||||
GameboyJS.opcodeCbmap = cbmap;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,36 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// A RomAjaxReader is able to load a file through an AJAX request
|
|
||||||
var RomAjaxReader = function() {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// The callback argument will be called when a file is successfully
|
|
||||||
// read, with the data as argument (Uint8Array)
|
|
||||||
RomAjaxReader.prototype.setCallback = function(onLoadCallback) {
|
|
||||||
this.callback = onLoadCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This function should be called by application code
|
|
||||||
// and will trigger the AJAX call itself and push data to the ROM object
|
|
||||||
RomAjaxReader.prototype.loadFromUrl = function(url) {
|
|
||||||
if (!url) {
|
|
||||||
throw 'No url has been set in order to load a ROM file.';
|
|
||||||
}
|
|
||||||
var cb = this.callback;
|
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', url, true);
|
|
||||||
xhr.responseType = "arraybuffer";
|
|
||||||
xhr.onload = function() {
|
|
||||||
var rom = new Uint8Array(xhr.response);
|
|
||||||
cb && cb(rom);
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.RomAjaxReader = RomAjaxReader;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,65 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// A RomDropFileReader is able to load a drag and dropped file
|
|
||||||
var RomDropFileReader = function(el) {
|
|
||||||
this.dropElement = el;
|
|
||||||
if (!this.dropElement) {
|
|
||||||
throw 'The RomDropFileReader needs a drop zone.';
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.dropElement.addEventListener('dragenter', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (e.target !== self.dropElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.dropElement.classList.add('drag-active');
|
|
||||||
});
|
|
||||||
this.dropElement.addEventListener('dragleave', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (e.target !== self.dropElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.dropElement.classList.remove('drag-active');
|
|
||||||
});
|
|
||||||
this.dropElement.addEventListener('dragover', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
self.dropElement.classList.add('drag-active');
|
|
||||||
});
|
|
||||||
this.dropElement.addEventListener('drop', function (e) {
|
|
||||||
self.dropElement.classList.remove('drag-active');
|
|
||||||
if (e.dataTransfer.files.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
e.preventDefault();
|
|
||||||
self.loadFromFile(e.dataTransfer.files[0]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// The callback argument will be called when a file is successfully
|
|
||||||
// read, with the data as argument (Uint8Array)
|
|
||||||
RomDropFileReader.prototype.setCallback = function(onLoadCallback) {
|
|
||||||
this.callback = onLoadCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The file loading logic is the same as the regular file reader
|
|
||||||
RomDropFileReader.prototype.loadFromFile = function(file) {
|
|
||||||
if (file === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var fr = new FileReader();
|
|
||||||
var cb = this.callback;
|
|
||||||
|
|
||||||
fr.onload = function() {
|
|
||||||
cb && cb(new Uint8Array(fr.result));
|
|
||||||
};
|
|
||||||
fr.onerror = function(e) {
|
|
||||||
console.log('Error reading the file', e.target.error.code)
|
|
||||||
};
|
|
||||||
fr.readAsArrayBuffer(file);
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.RomDropFileReader = RomDropFileReader;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,45 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// A RomFileReader is able to load a local file from an input element
|
|
||||||
//
|
|
||||||
// Expects to be provided a file input element,
|
|
||||||
// or will try to find one with the "file" DOM ID
|
|
||||||
var RomFileReader = function(el) {
|
|
||||||
this.domElement = el || document.getElementById('file');
|
|
||||||
if (!this.domElement) {
|
|
||||||
throw 'The RomFileReader needs a valid input element.';
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.domElement.addEventListener('change', function(e){
|
|
||||||
self.loadFromFile(e.target.files[0]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// The callback argument will be called when a file is successfully
|
|
||||||
// read, with the data as argument (Uint8Array)
|
|
||||||
RomFileReader.prototype.setCallback = function(onLoadCallback) {
|
|
||||||
this.callback = onLoadCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Automatically called when the DOM input is provided with a file
|
|
||||||
RomFileReader.prototype.loadFromFile = function(file) {
|
|
||||||
if (file === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var fr = new FileReader();
|
|
||||||
var cb = this.callback;
|
|
||||||
|
|
||||||
fr.onload = function() {
|
|
||||||
cb && cb(new Uint8Array(fr.result));
|
|
||||||
};
|
|
||||||
fr.onerror = function(e) {
|
|
||||||
console.log('Error reading the file', e.target.error.code)
|
|
||||||
};
|
|
||||||
fr.readAsArrayBuffer(file);
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.RomFileReader = RomFileReader;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,35 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
var Rom = function(gameboy, romReader) {
|
|
||||||
this.gameboy = gameboy;
|
|
||||||
if (romReader) {
|
|
||||||
this.addReader(romReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Rom.prototype.addReader = function(romReader) {
|
|
||||||
var self = this;
|
|
||||||
romReader.setCallback(function(data) {
|
|
||||||
if (!validate(data)) {
|
|
||||||
self.gameboy.error('The file is not a valid GameBoy ROM.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.data = data;
|
|
||||||
self.gameboy.startRom(self);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Validate the checksum of the cartridge header
|
|
||||||
function validate(data) {
|
|
||||||
var hash = 0;
|
|
||||||
for (var i = 0x134; i <= 0x14C; i++) {
|
|
||||||
hash = hash - data[i] - 1;
|
|
||||||
}
|
|
||||||
return (hash & 0xFF) == data[0x14D];
|
|
||||||
};
|
|
||||||
|
|
||||||
GameboyJS.Rom = Rom;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,43 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Handlers for the Serial port of the Gameboy
|
|
||||||
|
|
||||||
// The ConsoleSerial is an output-only serial port
|
|
||||||
// designed for debug purposes as some test roms output data on the serial port
|
|
||||||
//
|
|
||||||
// Will regularly output the received byte (converted to string) in the console logs
|
|
||||||
// This handler always push the value 0xFF as an input
|
|
||||||
var ConsoleSerial = {
|
|
||||||
current: '',
|
|
||||||
timeout: null,
|
|
||||||
out: function(data) {
|
|
||||||
ConsoleSerial.current += String.fromCharCode(data);
|
|
||||||
if (data == 10) {
|
|
||||||
ConsoleSerial.print();
|
|
||||||
} else {
|
|
||||||
clearTimeout(ConsoleSerial.timeout);
|
|
||||||
ConsoleSerial.timeout = setTimeout(ConsoleSerial.print, 500);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
in: function() {
|
|
||||||
return 0xFF;
|
|
||||||
},
|
|
||||||
print: function() {
|
|
||||||
clearTimeout(ConsoleSerial.timeout);
|
|
||||||
console.log('serial: '+ConsoleSerial.current);
|
|
||||||
ConsoleSerial.current = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
GameboyJS.ConsoleSerial = ConsoleSerial;
|
|
||||||
|
|
||||||
// A DummySerial outputs nothing and always inputs 0xFF
|
|
||||||
var DummySerial = {
|
|
||||||
out: function() {},
|
|
||||||
in: function() {
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
GameboyJS.DummySerial = DummySerial;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
212
src/sound/apu.js
212
src/sound/apu.js
|
@ -1,212 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Audio Processing unit
|
|
||||||
// Listens the write accesses to the audio-reserved memory addresses
|
|
||||||
// and dispatches the data to the sound channels
|
|
||||||
var APU = function(memory) {
|
|
||||||
this.memory = memory;
|
|
||||||
this.enabled = false;
|
|
||||||
|
|
||||||
var AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
||||||
var audioContext = new AudioContext();
|
|
||||||
|
|
||||||
this.channel1 = new GameboyJS.Channel1(this, 1, audioContext);
|
|
||||||
this.channel2 = new GameboyJS.Channel1(this, 2, audioContext);
|
|
||||||
this.channel3 = new GameboyJS.Channel3(this, 3, audioContext);
|
|
||||||
this.channel4 = new GameboyJS.Channel4(this, 4, audioContext);
|
|
||||||
|
|
||||||
};
|
|
||||||
APU.prototype.connect = function() {
|
|
||||||
this.channel1.enable();
|
|
||||||
this.channel2.enable();
|
|
||||||
this.channel3.enable();
|
|
||||||
};
|
|
||||||
APU.prototype.disconnect = function() {
|
|
||||||
this.channel1.disable();
|
|
||||||
this.channel2.disable();
|
|
||||||
this.channel3.disable();
|
|
||||||
};
|
|
||||||
// Updates the states of each channel given the elapsed time
|
|
||||||
// (in instructions) since last update
|
|
||||||
APU.prototype.update = function(clockElapsed) {
|
|
||||||
if (this.enabled == false) return;
|
|
||||||
|
|
||||||
this.channel1.update(clockElapsed);
|
|
||||||
this.channel2.update(clockElapsed);
|
|
||||||
this.channel3.update(clockElapsed);
|
|
||||||
this.channel4.update(clockElapsed);
|
|
||||||
};
|
|
||||||
APU.prototype.setSoundFlag = function(channel, value) {
|
|
||||||
var mask = 0xFF - (1 << (channel - 1));
|
|
||||||
value = value << (channel - 1)
|
|
||||||
var byteValue = this.memory.rb(APU.registers.NR52);
|
|
||||||
byteValue &= mask;
|
|
||||||
byteValue |= value;
|
|
||||||
this.memory[APU.registers.NR52] = byteValue;
|
|
||||||
};
|
|
||||||
// Manage writes to audio registers
|
|
||||||
// Will update the channels depending on the address
|
|
||||||
APU.prototype.manageWrite = function(addr, value) {
|
|
||||||
if (this.enabled == false && addr < APU.registers.NR52) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.memory[addr] = value;
|
|
||||||
|
|
||||||
switch (addr) {
|
|
||||||
// Channel 1 addresses
|
|
||||||
case 0xFF10:
|
|
||||||
this.channel1.clockSweep = 0;
|
|
||||||
this.channel1.sweepTime = ((value & 0x70) >> 4);
|
|
||||||
this.channel1.sweepSign = (value & 0x08) ? -1 : 1;
|
|
||||||
this.channel1.sweepShifts = (value & 0x07);
|
|
||||||
this.channel1.sweepCount = this.channel1.sweepShifts;
|
|
||||||
break;
|
|
||||||
case 0xFF11:
|
|
||||||
// todo : bits 6-7
|
|
||||||
this.channel1.setLength(value & 0x3F);
|
|
||||||
break;
|
|
||||||
case 0xFF12:
|
|
||||||
this.channel1.envelopeSign = (value & 0x08) ? 1 : -1;
|
|
||||||
var envelopeVolume = (value & 0xF0) >> 4;
|
|
||||||
this.channel1.setEnvelopeVolume(envelopeVolume);
|
|
||||||
this.channel1.envelopeStep = (value & 0x07);
|
|
||||||
break;
|
|
||||||
case 0xFF13:
|
|
||||||
var frequency = this.channel1.getFrequency();
|
|
||||||
frequency &= 0xF00;
|
|
||||||
frequency |= value;
|
|
||||||
this.channel1.setFrequency(frequency);
|
|
||||||
break;
|
|
||||||
case 0xFF14:
|
|
||||||
var frequency = this.channel1.getFrequency();
|
|
||||||
frequency &= 0xFF;
|
|
||||||
frequency |= (value & 7) << 8;
|
|
||||||
this.channel1.setFrequency(frequency);
|
|
||||||
this.channel1.lengthCheck = (value & 0x40) ? true : false;
|
|
||||||
if (value & 0x80) this.channel1.play();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Channel 2 addresses
|
|
||||||
case 0xFF16:
|
|
||||||
// todo : bits 6-7
|
|
||||||
this.channel2.setLength(value & 0x3F);
|
|
||||||
break;
|
|
||||||
case 0xFF17:
|
|
||||||
this.channel2.envelopeSign = (value & 0x08) ? 1 : -1;
|
|
||||||
var envelopeVolume = (value & 0xF0) >> 4;
|
|
||||||
this.channel2.setEnvelopeVolume(envelopeVolume);
|
|
||||||
this.channel2.envelopeStep = (value & 0x07);
|
|
||||||
break;
|
|
||||||
case 0xFF18:
|
|
||||||
var frequency = this.channel2.getFrequency();
|
|
||||||
frequency &= 0xF00;
|
|
||||||
frequency |= value;
|
|
||||||
this.channel2.setFrequency(frequency);
|
|
||||||
break;
|
|
||||||
case 0xFF19:
|
|
||||||
var frequency = this.channel2.getFrequency();
|
|
||||||
frequency &= 0xFF;
|
|
||||||
frequency |= (value & 7) << 8;
|
|
||||||
this.channel2.setFrequency(frequency);
|
|
||||||
this.channel2.lengthCheck = (value & 0x40) ? true : false;
|
|
||||||
if (value & 0x80) {
|
|
||||||
this.channel2.play();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Channel 3 addresses
|
|
||||||
case 0xFF1A:
|
|
||||||
// todo
|
|
||||||
break;
|
|
||||||
case 0xFF1B:
|
|
||||||
this.channel3.setLength(value);
|
|
||||||
break;
|
|
||||||
case 0xFF1C:
|
|
||||||
// todo
|
|
||||||
break;
|
|
||||||
case 0xFF1D:
|
|
||||||
var frequency = this.channel3.getFrequency();
|
|
||||||
frequency &= 0xF00;
|
|
||||||
frequency |= value;
|
|
||||||
this.channel3.setFrequency(frequency);
|
|
||||||
break;
|
|
||||||
case 0xFF1E:
|
|
||||||
var frequency = this.channel3.getFrequency();
|
|
||||||
frequency &= 0xFF;
|
|
||||||
frequency |= (value & 7) << 8;
|
|
||||||
this.channel3.setFrequency(frequency);
|
|
||||||
this.channel3.lengthCheck = (value & 0x40) ? true : false;
|
|
||||||
if (value & 0x80) {
|
|
||||||
this.channel3.play();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Channel 4 addresses
|
|
||||||
case 0xFF20:
|
|
||||||
this.channel4.setLength(value & 0x3F);
|
|
||||||
break;
|
|
||||||
case 0xFF21:
|
|
||||||
// todo
|
|
||||||
break;
|
|
||||||
case 0xFF22:
|
|
||||||
// todo
|
|
||||||
break;
|
|
||||||
case 0xFF23:
|
|
||||||
this.channel4.lengthCheck = (value & 0x40) ? true : false;
|
|
||||||
if (value & 0x80) {
|
|
||||||
this.channel4.play();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// channel 3 wave bytes
|
|
||||||
case 0xFF30:case 0xFF31:case 0xFF32:case 0xFF33:case 0xFF34:case 0xFF35:case 0xFF36:case 0xFF37:
|
|
||||||
case 0xFF38:case 0xFF39:case 0xFF3A:case 0xFF3B:case 0xFF3C:case 0xFF3D:case 0xFF3E:case 0xFF3F:
|
|
||||||
var index = addr - 0xFF30;
|
|
||||||
this.channel3.setWaveBufferByte(index, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// general audio switch
|
|
||||||
case 0xFF26:
|
|
||||||
value &= 0xF0;
|
|
||||||
this.memory[addr] = value;
|
|
||||||
this.enabled = (value & 0x80) == 0 ? false : true;
|
|
||||||
if (!this.enabled) {
|
|
||||||
for (var i = 0xFF10; i < 0xFF27; i++)
|
|
||||||
this.memory[i] = 0;
|
|
||||||
// todo stop sound
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
APU.registers = {
|
|
||||||
NR10: 0xFF10,
|
|
||||||
NR11: 0xFF11,
|
|
||||||
NR12: 0xFF12,
|
|
||||||
NR13: 0xFF13,
|
|
||||||
NR14: 0xFF14,
|
|
||||||
|
|
||||||
NR21: 0xFF16,
|
|
||||||
NR22: 0xFF17,
|
|
||||||
NR23: 0xFF18,
|
|
||||||
NR24: 0xFF19,
|
|
||||||
|
|
||||||
NR30: 0xFF1A,
|
|
||||||
NR31: 0xFF1B,
|
|
||||||
NR32: 0xFF1C,
|
|
||||||
NR33: 0xFF1D,
|
|
||||||
NR34: 0xFF1E,
|
|
||||||
|
|
||||||
NR41: 0xFF20,
|
|
||||||
NR42: 0xFF21,
|
|
||||||
NR43: 0xFF22,
|
|
||||||
NR44: 0xFF23,
|
|
||||||
|
|
||||||
NR50: 0xFF24,
|
|
||||||
NR51: 0xFF25,
|
|
||||||
NR52: 0xFF26
|
|
||||||
};
|
|
||||||
GameboyJS.APU = APU;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,129 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
var Channel1 = function(apu, channelNumber, audioContext) {
|
|
||||||
this.apu = apu;
|
|
||||||
this.channelNumber = channelNumber;
|
|
||||||
this.playing = false;
|
|
||||||
|
|
||||||
this.soundLengthUnit = 0x4000; // 1 / 256 second of instructions
|
|
||||||
this.soundLength = 64; // defaults to 64 periods
|
|
||||||
this.lengthCheck = false;
|
|
||||||
|
|
||||||
this.sweepTime = 0; // from 0 to 7
|
|
||||||
this.sweepStepLength = 0x8000; // 1 / 128 seconds of instructions
|
|
||||||
this.sweepCount = 0;
|
|
||||||
this.sweepShifts = 0;
|
|
||||||
this.sweepSign = 1; // +1 / -1 for increase / decrease freq
|
|
||||||
|
|
||||||
this.frequency = 0;
|
|
||||||
|
|
||||||
this.envelopeStep = 0;
|
|
||||||
this.envelopeStepLength = 0x10000;// 1 / 64 seconds of instructions
|
|
||||||
this.envelopeCheck = false;
|
|
||||||
this.envelopeSign = 1;
|
|
||||||
|
|
||||||
this.clockLength = 0;
|
|
||||||
this.clockEnvelop = 0;
|
|
||||||
this.clockSweep = 0;
|
|
||||||
|
|
||||||
var gainNode = audioContext.createGain();
|
|
||||||
gainNode.gain.value = 0;
|
|
||||||
var oscillator = audioContext.createOscillator();
|
|
||||||
oscillator.type = 'square';
|
|
||||||
oscillator.frequency.value = 1000;
|
|
||||||
oscillator.connect(gainNode);
|
|
||||||
oscillator.start(0);
|
|
||||||
|
|
||||||
this.audioContext = audioContext;
|
|
||||||
this.gainNode = gainNode;
|
|
||||||
this.oscillator = oscillator;
|
|
||||||
};
|
|
||||||
|
|
||||||
Channel1.prototype.play = function() {
|
|
||||||
if (this.playing) return;
|
|
||||||
this.playing = true;
|
|
||||||
this.apu.setSoundFlag(this.channelNumber, 1);
|
|
||||||
this.gainNode.connect(this.audioContext.destination);
|
|
||||||
this.clockLength = 0;
|
|
||||||
this.clockEnvelop = 0;
|
|
||||||
this.clockSweep = 0;
|
|
||||||
if (this.sweepShifts > 0) this.checkFreqSweep();
|
|
||||||
};
|
|
||||||
Channel1.prototype.stop = function() {
|
|
||||||
this.playing = false;
|
|
||||||
this.apu.setSoundFlag(this.channelNumber, 0);
|
|
||||||
this.gainNode.disconnect();
|
|
||||||
};
|
|
||||||
Channel1.prototype.checkFreqSweep = function() {
|
|
||||||
var oldFreq = this.getFrequency();
|
|
||||||
var newFreq = oldFreq + this.sweepSign * (oldFreq >> this.sweepShifts);
|
|
||||||
if (newFreq > 0x7FF) {
|
|
||||||
newFreq = 0;
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
return newFreq;
|
|
||||||
};
|
|
||||||
Channel1.prototype.update = function(clockElapsed) {
|
|
||||||
this.clockEnvelop += clockElapsed;
|
|
||||||
this.clockSweep += clockElapsed;
|
|
||||||
|
|
||||||
if ((this.sweepCount || this.sweepTime) && this.clockSweep > (this.sweepStepLength * this.sweepTime)) {
|
|
||||||
this.clockSweep -= (this.sweepStepLength * this.sweepTime);
|
|
||||||
this.sweepCount--;
|
|
||||||
|
|
||||||
var newFreq = this.checkFreqSweep(); // process and check new freq
|
|
||||||
|
|
||||||
this.apu.memory[0xFF13] = newFreq & 0xFF;
|
|
||||||
this.apu.memory[0xFF14] &= 0xF8;
|
|
||||||
this.apu.memory[0xFF14] |= (newFreq & 0x700) >> 8;
|
|
||||||
this.setFrequency(newFreq);
|
|
||||||
|
|
||||||
this.checkFreqSweep(); // check again with new value
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.envelopeCheck && this.clockEnvelop > this.envelopeStepLength) {
|
|
||||||
this.clockEnvelop -= this.envelopeStepLength;
|
|
||||||
this.envelopeStep--;
|
|
||||||
this.setEnvelopeVolume(this.envelopeVolume + this.envelopeSign);
|
|
||||||
if (this.envelopeStep <= 0) {
|
|
||||||
this.envelopeCheck = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.lengthCheck) {
|
|
||||||
this.clockLength += clockElapsed;
|
|
||||||
if (this.clockLength > this.soundLengthUnit) {
|
|
||||||
this.soundLength--;
|
|
||||||
this.clockLength -= this.soundLengthUnit;
|
|
||||||
if (this.soundLength == 0) {
|
|
||||||
this.setLength(0);
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Channel1.prototype.setFrequency = function(value) {
|
|
||||||
this.frequency = value;
|
|
||||||
this.oscillator.frequency.value = 131072 / (2048 - this.frequency);
|
|
||||||
};
|
|
||||||
Channel1.prototype.getFrequency = function() {
|
|
||||||
return this.frequency;
|
|
||||||
};
|
|
||||||
Channel1.prototype.setLength = function(value) {
|
|
||||||
this.soundLength = 64 - (value & 0x3F);
|
|
||||||
};
|
|
||||||
Channel1.prototype.setEnvelopeVolume = function(volume) {
|
|
||||||
this.envelopeCheck = volume > 0 && volume < 16 ? true : false;
|
|
||||||
this.envelopeVolume = volume;
|
|
||||||
this.gainNode.gain.value = this.envelopeVolume * 1/100;
|
|
||||||
};
|
|
||||||
Channel1.prototype.disable = function() {
|
|
||||||
this.oscillator.disconnect();
|
|
||||||
};
|
|
||||||
Channel1.prototype.enable = function() {
|
|
||||||
this.oscillator.connect(this.gainNode);
|
|
||||||
};
|
|
||||||
GameboyJS.Channel1 = Channel1;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,86 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
var Channel3 = function(apu, channelNumber, audioContext) {
|
|
||||||
this.apu = apu;
|
|
||||||
this.channelNumber = channelNumber;
|
|
||||||
this.playing = false;
|
|
||||||
|
|
||||||
this.soundLength = 0;
|
|
||||||
this.soundLengthUnit = 0x4000; // 1 / 256 second of instructions
|
|
||||||
this.lengthCheck = false;
|
|
||||||
|
|
||||||
this.clockLength = 0;
|
|
||||||
|
|
||||||
this.buffer = new Float32Array(32);
|
|
||||||
|
|
||||||
var gainNode = audioContext.createGain();
|
|
||||||
gainNode.gain.value = 1;
|
|
||||||
this.gainNode = gainNode;
|
|
||||||
|
|
||||||
this.baseSpeed = 65536;
|
|
||||||
var waveBuffer = audioContext.createBuffer(1, 32, this.baseSpeed);
|
|
||||||
|
|
||||||
var bufferSource = audioContext.createBufferSource();
|
|
||||||
bufferSource.buffer = waveBuffer;
|
|
||||||
bufferSource.loop = true;
|
|
||||||
bufferSource.connect(gainNode);
|
|
||||||
bufferSource.start(0);
|
|
||||||
|
|
||||||
this.audioContext = audioContext;
|
|
||||||
this.waveBuffer = waveBuffer;
|
|
||||||
this.bufferSource = bufferSource;
|
|
||||||
|
|
||||||
};
|
|
||||||
Channel3.prototype.play = function() {
|
|
||||||
if (this.playing) return;
|
|
||||||
this.playing = true;
|
|
||||||
this.apu.setSoundFlag(this.channelNumber, 1);
|
|
||||||
this.waveBuffer.copyToChannel(this.buffer, 0, 0);
|
|
||||||
|
|
||||||
this.gainNode.connect(this.audioContext.destination);
|
|
||||||
this.clockLength = 0;
|
|
||||||
};
|
|
||||||
Channel3.prototype.stop = function() {
|
|
||||||
this.playing = false;
|
|
||||||
this.apu.setSoundFlag(this.channelNumber, 0);
|
|
||||||
this.gainNode.disconnect();
|
|
||||||
};
|
|
||||||
Channel3.prototype.update = function(clockElapsed) {
|
|
||||||
if (this.lengthCheck){
|
|
||||||
this.clockLength += clockElapsed;
|
|
||||||
if (this.clockLength > this.soundLengthUnit) {
|
|
||||||
this.soundLength--;
|
|
||||||
this.clockLength -= this.soundLengthUnit;
|
|
||||||
if (this.soundLength == 0) {
|
|
||||||
this.setLength(0);
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Channel3.prototype.setFrequency = function(value) {
|
|
||||||
value = 65536 / (2048 - value);
|
|
||||||
this.bufferSource.playbackRate.value = value / this.baseSpeed;
|
|
||||||
};
|
|
||||||
Channel3.prototype.getFrequency = function() {
|
|
||||||
var freq = 2048 - 65536 / (this.bufferSource.playbackRate.value * this.baseSpeed);
|
|
||||||
return freq | 1;
|
|
||||||
};
|
|
||||||
Channel3.prototype.setLength = function(value) {
|
|
||||||
this.soundLength = 256 - value;
|
|
||||||
};
|
|
||||||
Channel3.prototype.setWaveBufferByte = function(index, value) {
|
|
||||||
var bufferIndex = index * 2;
|
|
||||||
|
|
||||||
this.buffer[bufferIndex] = (value >> 4) / 8 - 1; // value in buffer is in -1 -> 1
|
|
||||||
this.buffer[bufferIndex+1] = (value & 0x0F) / 8 - 1;
|
|
||||||
};
|
|
||||||
Channel3.prototype.disable = function() {
|
|
||||||
this.bufferSource.disconnect();
|
|
||||||
};
|
|
||||||
Channel3.prototype.enable = function() {
|
|
||||||
this.bufferSource.connect(this.gainNode);
|
|
||||||
};
|
|
||||||
GameboyJS.Channel3 = Channel3;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
|
@ -1,45 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
var Channel4 = function(apu, channelNumber, audioContext) {
|
|
||||||
this.apu = apu;
|
|
||||||
this.channelNumber = channelNumber;
|
|
||||||
this.playing = false;
|
|
||||||
|
|
||||||
this.soundLengthUnit = 0x4000; // 1 / 256 second of instructions
|
|
||||||
this.soundLength = 64; // defaults to 64 periods
|
|
||||||
this.lengthCheck = false;
|
|
||||||
|
|
||||||
this.clockLength = 0;
|
|
||||||
|
|
||||||
this.audioContext = audioContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
Channel4.prototype.play = function() {
|
|
||||||
if (this.playing) return;
|
|
||||||
this.playing = true;
|
|
||||||
this.apu.setSoundFlag(this.channelNumber, 1);
|
|
||||||
this.clockLength = 0;
|
|
||||||
};
|
|
||||||
Channel4.prototype.stop = function() {
|
|
||||||
this.playing = false;
|
|
||||||
this.apu.setSoundFlag(this.channelNumber, 0);
|
|
||||||
};
|
|
||||||
Channel4.prototype.update = function(clockElapsed) {
|
|
||||||
if (this.lengthCheck) {
|
|
||||||
this.clockLength += clockElapsed;
|
|
||||||
if (this.clockLength > this.soundLengthUnit) {
|
|
||||||
this.soundLength--;
|
|
||||||
this.clockLength -= this.soundLengthUnit;
|
|
||||||
if (this.soundLength == 0) {
|
|
||||||
this.setLength(0);
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Channel4.prototype.setLength = function(value) {
|
|
||||||
this.soundLength = 64 - (value & 0x3F);
|
|
||||||
};
|
|
||||||
GameboyJS.Channel4 = Channel4;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
66
src/timer.js
66
src/timer.js
|
@ -1,66 +0,0 @@
|
||||||
var GameboyJS;
|
|
||||||
(function (GameboyJS) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var Timer = function(cpu, memory) {
|
|
||||||
this.cpu = cpu;
|
|
||||||
this.memory = memory;
|
|
||||||
|
|
||||||
this.DIV = 0xFF04;
|
|
||||||
this.TIMA = 0xFF05;
|
|
||||||
this.TMA = 0xFF06;
|
|
||||||
this.TAC = 0xFF07;
|
|
||||||
|
|
||||||
this.mainTime = 0;
|
|
||||||
this.divTime = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Timer.prototype.update = function(clockElapsed) {
|
|
||||||
this.updateDiv(clockElapsed);
|
|
||||||
this.updateTimer(clockElapsed);
|
|
||||||
};
|
|
||||||
|
|
||||||
Timer.prototype.updateTimer = function(clockElapsed) {
|
|
||||||
if (!(this.memory.rb(this.TAC) & 0x4)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.mainTime += clockElapsed;
|
|
||||||
|
|
||||||
var threshold = 64;
|
|
||||||
switch (this.memory.rb(this.TAC) & 3) {
|
|
||||||
case 0: threshold=64; break; // 4KHz
|
|
||||||
case 1: threshold=1; break; // 256KHz
|
|
||||||
case 2: threshold=4; break; // 64KHz
|
|
||||||
case 3: threshold=16; break; // 16KHz
|
|
||||||
}
|
|
||||||
threshold *= 16;
|
|
||||||
|
|
||||||
while (this.mainTime >= threshold) {
|
|
||||||
this.mainTime -= threshold;
|
|
||||||
|
|
||||||
this.memory.wb(this.TIMA, this.memory.rb(this.TIMA) + 1);
|
|
||||||
if (this.memory.rb(this.TIMA) > 0xFF) {
|
|
||||||
this.memory.wb(this.TIMA, this.memory.rb(this.TMA));
|
|
||||||
this.cpu.requestInterrupt(GameboyJS.CPU.INTERRUPTS.TIMER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Update the DIV register internal clock
|
|
||||||
// Increment it if the clock threshold is elapsed and
|
|
||||||
// reset it if its value overflows
|
|
||||||
Timer.prototype.updateDiv = function(clockElapsed) {
|
|
||||||
var divThreshold = 256; // DIV is 16KHz
|
|
||||||
this.divTime += clockElapsed;
|
|
||||||
if (this.divTime > divThreshold) {
|
|
||||||
this.divTime -= divThreshold;
|
|
||||||
var div = this.memory.rb(this.DIV) + 1;
|
|
||||||
this.memory.wb(this.DIV, div&0xFF);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Timer.prototype.resetDiv = function() {
|
|
||||||
this.divTime = 0;
|
|
||||||
this.memory[this.DIV] = 0; // direct write to avoid looping
|
|
||||||
};
|
|
||||||
GameboyJS.Timer = Timer;
|
|
||||||
}(GameboyJS || (GameboyJS = {})));
|
|
Loading…
Add table
Add a link
Reference in a new issue