Skip to content
Snippets Groups Projects
Verified Commit 3b34cfd7 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: initial support for web

parent e3f188ab
No related branches found
No related tags found
1 merge request!2Initial web version of boytacean
...@@ -80,8 +80,8 @@ fn main() { ...@@ -80,8 +80,8 @@ fn main() {
let mut game_boy = GameBoy::new(); let mut game_boy = GameBoy::new();
game_boy.load_boot_default(); game_boy.load_boot_default();
game_boy.load_rom("../../res/roms/ld_r_r.gb"); game_boy.load_rom_file("../../res/roms/ld_r_r.gb");
//game_boy.load_rom("../../res/roms/opus5.gb"); //game_boy.load_rom_file("../../res/roms/opus5.gb");
let mut counter = 0; let mut counter = 0;
......
yarn.lock
package-lock.json
/.parcel-cache
/dist
/node_modules
{
"extends": "@parcel/config-default",
"transformers": {
"*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"],
"*.ch8": ["@parcel/transformer-raw"]
}
}
{
"semi": true,
"trailingComma": "none",
"singleQuote": false,
"tabWidth": 4,
"endOfLine": "crlf"
}
@import url("https://fonts.googleapis.com/css2?family=VT323&display=swap");
* {
box-sizing: border-box;
-o-box-sizing: border-box;
-ms-box-sizing: border-box;
-moz-box-sizing: border-box;
-khtml-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
a {
border-bottom: 2px dotted #ffffff;
color: #ffffff;
text-decoration: none;
}
a:hover {
border-bottom-style: solid;
}
html {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}
body {
color: #ffffff;
font-family: "VT323", "Robot", "Open Sans", Arial, Helvetica, sans-serif;
margin: 0px 0px 0px 0px;
padding: 12px 12px 52px 12px;
}
p {
font-size: 18px;
line-height: 24px;
margin: 12px 0px 12px 0px;
}
.main {
display: flex;
}
@media only screen and (max-width: 1120px) {
.main {
flex-direction: column;
}
}
.main > .side-left {
display: flex;
flex: 1 0;
justify-content: center;
text-align: center;
}
.main > .side-left .canvas-container {
max-width: 100%;
}
.main > .side-left .canvas-container.fullscreen {
align-items: center;
background-color: #2d2d2d;
display: flex;
height: 100%;
justify-content: center;
left: 0px;
position: fixed;
top: 0px;
width: 100%;
z-index: 6;
}
.main > .side-left .canvas-container > .canvas-close {
bottom: 22px;
display: none;
position: absolute;
right: 22px;
}
.main > .side-left .canvas-container > .canvas-close > img {
height: 32px;
width: 32px;
}
.main > .side-left .canvas-container.fullscreen > .canvas-close {
display: block;
}
.main > .side-left .canvas-container > .canvas-frame {
background-color: #1b1a17;
border: 2px solid #50cb93;
font-size: 0px;
margin-top: 78px;
max-width: 660px;
padding: 8px 8px 8px 8px;
}
@media only screen and (max-width: 1120px) {
.main > .side-left .canvas-container > .canvas-frame {
margin-top: 12px;
}
}
.main > .side-left .canvas-container.fullscreen > .canvas-frame {
background-color: transparent;
border: none;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
-o-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
-ms-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
-moz-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
-khtml-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
-webkit-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
margin: 0px 0px 0px 0px;
max-width: unset;
padding: 0px 0px 0px 0px;
}
.main > .side-left .canvas-container > .canvas-frame > .canvas {
width: 100%;
}
.main > .side-right {
flex: 0 1;
max-width: 100%;
min-width: 580px;
padding: 0px 24px 0px 24px;
}
@media only screen and (max-width: 1120px) {
.main > .side-right {
min-width: unset;
padding: 0px 0px 0px 0px;
}
}
.main > .side-right .logo-image {
vertical-align: middle;
width: 32px;
}
.main > .side-right .separator {
background: #ffffff;
height: 2px;
margin: 22px 0px 22px 0px;
}
.main > .side-right .diag {
font-size: 24px;
vertical-align: top;
}
.main > .side-right .diag > dt {
clear: both;
float: left;
margin-top: 12px;
}
.main > .side-right .diag > dt:first-of-type {
margin-top: 0px;
}
.main > .side-right .diag > dd {
float: right;
margin-top: 12px;
}
.main > .side-right .diag > dd:first-of-type {
margin-top: 0px;
}
.main > .side-right .diag::after {
clear: both;
content: '';
display: block;
}
.footer {
bottom: 0px;
height: 40px;
left: 0px;
line-height: 40px;
padding: 0px 0px 0px 0px;
position: fixed;
text-align: center;
width: 100%;
}
.footer-background {
bottom: 0px;
filter: blur(1.0rem);
-o-filter: blur(1.0rem);
-ms-filter: blur(1.0rem);
-moz-filter: blur(1.0rem);
-khtml-filter: blur(1.0rem);
-webkit-filter: blur(1.0rem);
height: 40px;
left: 0px;
position: fixed;
width: 100%;
}
.toast-container {
background-color: black;
height: 0px;
left: 0px;
padding: 0px 24px 0px 24px;
pointer-events: none;
position: fixed;
text-align: center;
top: 0px;
width: 100%;
z-index: 8;
}
.toast-container > .toast {
background-color: #2a9d8f;
border-radius: 4px 4px 4px 4px;
-o-border-radius: 4px 4px 4px 4px;
-ms-border-radius: 4px 4px 4px 4px;
-moz-border-radius: 4px 4px 4px 4px;
-khtml-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
cursor: pointer;
display: inline-block;
font-size: 20px;
line-height: 22px;
opacity: 0.0;
-o-opacity: 0.0;
-ms-opacity: 0.0;
-moz-opacity: 0.0;
-khtml-opacity: 0.0;
-webkit-opacity: 0.0;
padding: 12px 18px 12px 18px;
position: relative;
top: -46px;
transition: top 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: top 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: top 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: top 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: top 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: top 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
width: fit-content;
}
.toast-container > .toast.error {
background-color: #e63946;
}
.toast-container > .toast.visible {
opacity: 1.0;
-o-opacity: 1.0;
-ms-opacity: 1.0;
-moz-opacity: 1.0;
-khtml-opacity: 1.0;
-webkit-opacity: 1.0;
pointer-events: all;
top: 24px;
}
.button-area {
user-select: none;
-o-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
}
.button-area > * {
margin-bottom: 12px;
}
.magnify-button {
cursor: pointer;
display: inline-block;
transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.magnify-button:hover {
transform: scale(1.3, 1.3);
-o-transform: scale(1.3, 1.3);
-ms-transform: scale(1.3, 1.3);
-moz-transform: scale(1.3, 1.3);
-khtml-transform: scale(1.3, 1.3);
-webkit-transform: scale(1.3, 1.3);
}
.magnify-button:active {
transform: scale(1.0, 1.0);
-o-transform: scale(1.0, 1.0);
-ms-transform: scale(1.0, 1.0);
-moz-transform: scale(1.0, 1.0);
-khtml-transform: scale(1.0, 1.0);
-webkit-transform: scale(1.0, 1.0);
}
.tiny-button {
border-radius: 96px 96px 96px 96px;
-o-border-radius: 96px 96px 96px 96px;
-ms-border-radius: 96px 96px 96px 96px;
-moz-border-radius: 96px 96px 96px 96px;
-khtml-border-radius: 96px 96px 96px 96px;
-webkit-border-radius: 96px 96px 96px 96px;
cursor: pointer;
display: inline-block;
padding: 0px 8px 0px 8px;
user-select: none;
-o-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
}
.tiny-button.border {
border: 1px solid #ffffff;
}
.tiny-button.padded {
padding: 4px 10px 4px 10px;
}
.tiny-button.padded-large {
padding: 4px 14px 4px 14px;
}
.tiny-button.rounded {
padding: 6px 6px 6px 6px;
}
.tiny-button.enabled {
background-color: #50cb93;
}
.tiny-button.file {
position: relative;
}
.tiny-button:hover {
background-color: #50cb93;
}
.tiny-button.red:hover {
background-color: #e63946;
}
.tiny-button:active {
background-color: #2a9d8f;
}
.tiny-button.red:active {
background-color: #bf2a37;
}
.tiny-button > img {
margin-right: 6px;
margin-top: 2px;
vertical-align: top;
width: 13px;
}
.tiny-button > img.medium {
width: 20px;
}
.tiny-button > img.large {
width: 28px;
}
.tiny-button > img.very-large {
width: 38px;
}
.tiny-button.no-text > img {
margin-right: 0px;
margin-top: 0px;
}
.tiny-button.file > input[type="file"] {
cursor: pointer;
height: 100%;
left: 0px;
opacity: 0;
-o-opacity: 0;
-ms-opacity: 0;
-moz-opacity: 0;
-khtml-opacity: 0;
-webkit-opacity: 0;
position: absolute;
top: 0px;
vertical-align: top;
width: 100%;
}
.tiny-button.file > input[type="file"]::-webkit-file-upload-button {
cursor: pointer;
}
.overlay {
align-items: center;
background-color: rgba(80, 203, 147, 0.95);
display: flex;
font-size: 48px;
height: 100%;
justify-content: center;
left: 0px;
opacity: 0.0;
-o-opacity: 0.0;
-ms-opacity: 0.0;
-moz-opacity: 0.0;
-khtml-opacity: 0.0;
-webkit-opacity: 0.0;
pointer-events: none;
position: fixed;
text-align: center;
top: 0px;
transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
width: 100%;
z-index: 10;
}
.overlay.visible {
opacity: 1.0;
-o-opacity: 1.0;
-ms-opacity: 1.0;
-moz-opacity: 1.0;
-khtml-opacity: 1.0;
-webkit-opacity: 1.0;
}
.overlay .overlay-image {
margin-top: 16px;
}
.overlay .overlay-image > img {
width: 64px;
}
.modal-container {
align-items: center;
background-color: rgba(20, 20, 20, 0.95);
display: flex;
height: 100%;
justify-content: center;
left: 0px;
opacity: 0;
-o-opacity: 0;
-ms-opacity: 0;
-moz-opacity: 0;
-khtml-opacity: 0;
-webkit-opacity: 0;
padding: 0px 12px 0px 12px;
pointer-events: none;
position: fixed;
text-align: center;
top: 0px;
transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: opacity 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
width: 100%;
z-index: 10;
}
.modal-container.visible {
opacity: 1.0;
-o-opacity: 1.0;
-ms-opacity: 1.0;
-moz-opacity: 1.0;
-khtml-opacity: 1.0;
-webkit-opacity: 1.0;
transition: opacity 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: opacity 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: opacity 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: opacity 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: opacity 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: opacity 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.modal-container > .modal {
background-color: #264653;
border-radius: 6px 6px 6px 6px;
-o-border-radius: 6px 6px 6px 6px;
-ms-border-radius: 6px 6px 6px 6px;
-moz-border-radius: 6px 6px 6px 6px;
-khtml-border-radius: 6px 6px 6px 6px;
-webkit-border-radius: 6px 6px 6px 6px;
box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.24);
-o-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.24);
-ms-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.24);
-moz-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.24);
-khtml-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.24);
-webkit-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.24);
max-width: 100%;
padding: 24px 24px 24px 24px;
text-align: left;
transform: scale(0.96);
-o-transform: scale(0.96);
-ms-transform: scale(0.96);
-moz-transform: scale(0.96);
-khtml-transform: scale(0.96);
-webkit-transform: scale(0.96);
transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: transform 0.35s cubic-bezier(0.075, 0.82, 0.165, 1);
width: 480px;
}
.modal-container.visible > .modal {
pointer-events: all;
transform: scale(1);
-o-transform: scale(1);
-ms-transform: scale(1);
-moz-transform: scale(1);
-khtml-transform: scale(1);
-webkit-transform: scale(1);
transition: transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-o-transition: transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-ms-transition: transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-moz-transition: transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-khtml-transition: transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
-webkit-transition: transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.modal-container > .modal .modal-top-buttons {
float: right;
margin-right: -10px;
margin-top: -10px;
}
.modal-container > .modal .modal-title {
font-size: 32px;
margin-top: 0px;
text-align: left;
}
.modal-container > .modal .modal-text {
font-size: 20px;
line-height: 22px;
}
.modal-container > .modal .modal-buttons {
font-size: 22px;
margin-top: 24px;
text-align: center;
user-select: none;
-o-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
}
.modal-container > .modal .modal-buttons > .tiny-button {
margin-right: 12px;
min-width: 120px;
}
.modal-container > .modal .modal-buttons > .tiny-button:last-child {
margin-right: 0px;
}
.keyboard {
font-size: 0px;
text-align: center;
touch-callout: none;
-o-touch-callout: none;
-ms-touch-callout: none;
-moz-touch-callout: none;
-khtml-touch-callout: none;
-webkit-touch-callout: none;
user-select: none;
-o-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
}
.keyboard > .keyboard-line {
margin-bottom: 12px;
}
.keyboard > .keyboard-line:last-child {
margin-bottom: 0px;
}
.keyboard .key {
border: 2px solid #ffffff;
border-radius: 5px 5px 5px 5px;
-o-border-radius: 5px 5px 5px 5px;
-ms-border-radius: 5px 5px 5px 5px;
-moz-border-radius: 5px 5px 5px 5px;
-khtml-border-radius: 5px 5px 5px 5px;
-webkit-border-radius: 5px 5px 5px 5px;
cursor: pointer;
display: inline-block;
font-size: 38px;
height: 48px;
line-height: 46px;
margin-right: 14px;
text-align: center;
width: 48px;
}
.keyboard .key:last-child {
margin-right: 0px;
}
.keyboard .key:hover {
background-color: #50cb93;
}
.keyboard .key:active {
background-color: #2a9d8f;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Boytacean</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="Game Boy emulator written in Rust 🦀." />
<meta name="viewport"
content="width=device-width, user-scalable=yes, initial-scale=1, minimum-scale=1, maximum-scale=5" />
<link rel="icon" href="res/icon.png" />
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div class="main">
<div class="side-left">
<div id="canvas-container" class="canvas-container">
<span id="canvas-close" class="magnify-button canvas-close">
<img class="large" src="res/minimise.svg" alt="minimise" />
</span>
<div class="canvas-frame">
<canvas id="chip-canvas" class="canvas" width="640" height="320"></canvas>
</div>
</div>
</div>
<div class="side-right">
<h1>Boytacean <a id="version" href="https://gitlab.stage.hive.pt/joamag/boytacean/-/blob/master/CHANGELOG.md" target="_blank"></a> <img class="logo-image" src="res/thunder.png" alt="thunder" />
</h1>
<div class="separator"></div>
<div id="section-narrative" class="section">
<p>This is a <a href="https://en.wikipedia.org/wiki/Game_Boy" target="_blank">Game Boy</a> emulator built using
the <a href="https://www.rust-lang.org" target="_blank">Rust Programming Language</a> and is running
inside this browser with the help of <a href="https://webassembly.org/" target="_blank">WebAssembly</a>.
</p>
<p>You can check the source code of it at <a href="https://gitlab.stage.hive.pt/joamag/boytacean"
target="_blank">GitLab</a>.</p>
<p>TIP: Drag and Drop ROM files to the Browser to load the ROM.</p>
</div>
<div id="separator-narrative" class="separator"></div>
<div id="section-keyboard" class="section" style="display: none;">
<div id="keyboard" class="keyboard">
<div class="keyboard-line">
<span class="key">1</span>
<span class="key">2</span>
<span class="key">3</span>
<span class="key">4</span>
</div>
<div class="keyboard-line">
<span class="key">Q</span>
<span class="key">W</span>
<span class="key">E</span>
<span class="key">R</span>
</div>
<div class="keyboard-line">
<span class="key">A</span>
<span class="key">S</span>
<span class="key">D</span>
<span class="key">F</span>
</div>
<div class="keyboard-line">
<span class="key">Z</span>
<span class="key">X</span>
<span class="key">C</span>
<span class="key">V</span>
</div>
</div>
</div>
<div id="separator-keyboard" class="separator" style="display: none;"></div>
<div id="section-diag" class="section">
<dl class="diag">
<dt>Engine</dt>
<dd id="engine" class="tiny-button">-</dd>
<dt>ROM</dt>
<dd id="rom-name">-</dd>
<dt>ROM Size</dt>
<dd><span id="rom-size">-</span> bytes</dd>
<dt>CPU Frequency</dt>
<dd>
<span id="logic-frequency-minus" class="tiny-button">-</span>
<span id="logic-frequency">-</span> Hz
<span id="logic-frequency-plus" class="tiny-button">+</span></dd>
<dt>Framerate</dt>
<dd><span id="fps-count">-</span> fps</dd>
</dl>
</div>
<div id="separator-diag" class="separator"></div>
<div class="section">
<div class="button-area">
<span id="button-pause" class="tiny-button border padded">
<img src="res/pause.svg" alt="pause" /><span>Pause</span>
</span>
<span id="button-reset" class="tiny-button border padded">
<img src="res/reset.svg" alt="reset" /><span>Reset</span>
</span>
<span id="button-benchmark" class="tiny-button border padded">
<img src="res/bolt.svg" alt="bolt" /><span>Benchmark</span>
</span>
<span id="button-fullscreen" class="tiny-button border padded">
<img src="res/maximise.svg" alt="maximise" /><span>Fullscreen</span>
</span>
<span id="button-keyboard" class="tiny-button border padded">
<img src="res/dialpad.svg" alt="info" /><span>Keyboard</span>
</span>
<span id="button-information" class="tiny-button border padded enabled">
<img src="res/info.svg" alt="info" /><span>Information</span>
</span>
<span id="button-debug" class="tiny-button border padded">
<img src="res/bug.svg" alt="bug" /><span>Debug</span>
</span>
<span id="button-theme" class="tiny-button border padded">
<img src="res/marker.svg" alt="marker" /><span>Theme</span>
</span>
<span id="button-upload" class="tiny-button border padded file">
<img src="res/upload.svg" alt="upload" /><span>Upload ROM</span>
<input type="file" id="button-upload-file" name="button-upload-file" accept=".ch8">
</span>
</div>
</div>
</div>
</div>
<div class="toast-container">
<div id="toast" class="toast"></div>
</div>
</body>
<div id="modal-container" class="modal-container">
<div id="modal" class="modal">
<div class="modal-top-buttons">
<span id="modal-close" class="tiny-button rounded no-text">
<img class="medium" src="res/close.svg" alt="close" />
</span>
</div>
<h2 id="modal-title" class="modal-title"></h2>
<p id="modal-text" class="modal-text"></p>
<div class="modal-buttons">
<span id="modal-cancel" class="tiny-button red border padded-large">Cancel</span>
<span id="modal-confirm" class="tiny-button border padded-large">Confirm</span>
</div>
</div>
</div>
<div id="overlay" class="overlay">
<div class="overlay-container">
<div class="overlay-text">
Drag to load ROM <span id="rom-name"></span>
</div>
<div class="overlay-image">
<img src="res/sunglasses.png" alt="sunglasses" />
</div>
</div>
</div>
<div id="footer-background" class="footer-background"></div>
<div id="footer" class="footer">
Built with ❤️ by <a href="https://joao.me" target="_blank">João Magalhães</a>
</div>
<script type="module" src="index.ts"></script>
</body>
</html>
This diff is collapsed.
{
"name": "boytacean-web",
"version": "0.1.0",
"description": "The web version of Boytacean",
"repository": {
"type": "git",
"url": "git+https://gitlab.stage.hive.pt/joamag/boytacean.git"
},
"license": "Apache-2.0",
"scripts": {
"build": "parcel build index.html",
"dev": "parcel index.html",
"pretty": "prettier --config .prettierrc \"./**/*.{ts,json}\" --write",
"start": "npm run build",
"watch": "parcel watch index.html"
},
"source": "index.ts",
"devDependencies": {
"@parcel/transformer-typescript-tsc": "^2.6.1",
"parcel": "^2.6.1",
"prettier": "^2.7.1",
"typescript": "^4.5.5"
}
}
{
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"target": "es6",
"noImplicitAny": true,
"sourceMap": true,
"outDir": ".",
"baseUrl": ".",
"lib": ["es2015", "dom"],
"paths": {
"*": ["node_modules/*", "src/types/*"]
}
},
"include": ["**/*"],
"exclude": []
}
...@@ -37,18 +37,30 @@ impl GameBoy { ...@@ -37,18 +37,30 @@ impl GameBoy {
self.ppu().clock(cycles) self.ppu().clock(cycles)
} }
pub fn load_rom(&mut self, path: &str) { pub fn load_rom(&mut self, data: &[u8]) {
self.cpu.mmu().write_rom(0x0000, data);
}
pub fn load_rom_file(&mut self, path: &str) {
let data = read_file(path); let data = read_file(path);
self.cpu.mmu().write_rom(0x0000, &data); self.load_rom(&data);
}
pub fn load_boot(&mut self, data: &[u8]) {
self.cpu.mmu().write_boot(0x0000, data);
} }
pub fn load_boot(&mut self, path: &str) { pub fn load_boot_file(&mut self, path: &str) {
let data = read_file(path); let data = read_file(path);
self.cpu.mmu().write_boot(0x0000, &data); self.load_boot(&data);
} }
pub fn load_boot_default(&mut self) { pub fn load_boot_default(&mut self) {
self.load_boot("./res/dmg_rom.bin"); self.load_boot_file("./res/dmg_rom.bin");
}
pub fn frame_buffer_eager(&mut self) -> Vec<u8> {
self.frame_buffer().to_vec()
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment