├── README.md ├── css ├── GameBoy.css └── mobile.css ├── images ├── 128.png ├── gradient_01.svg ├── gradient_02.svg ├── gradient_03.svg ├── gradient_04.svg ├── gradient_05.svg ├── gradient_06.svg └── speaker.png ├── index.xhtml ├── js ├── GameBoyCore.js ├── GameBoyIO.js └── other │ ├── XAudioJS.swf │ ├── XAudioServer.js │ ├── XAudioServerMediaStreamWorker.js │ ├── base64.js │ ├── gui.js │ ├── json2.js │ ├── mobile.js │ ├── resampler.js │ ├── resize.js │ ├── resizeWorker.js │ ├── swfobject.js │ ├── terminal.js │ └── windowStack.js ├── manifest.webapp └── mobile.html /README.md: -------------------------------------------------------------------------------- 1 | JavaScript GameBoy Color Emulator 2 | ================================= 3 | 4 | **Copyright (C) 2010 - 2016 Grant Galitz** 5 | 6 | A GameBoy Color emulator that utilizes HTML5 canvas and JavaScript audio APIs to provide a full emulation of the console. 7 | 8 | **License:** 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | Known browsers to work well in: 17 | ------------------------------- 18 | 19 | * Firefox 4-27 (Windows 7, Windows Vista, Mac OS X) 20 | * Google Chrome 18+ 21 | * Safari 5.1.5+ 22 | 23 | Browsers that suck at performance or fail to run the code correctly: 24 | -------------------------------------------------------------------- 25 | 26 | * Firefox 4+ (*nix versions of Firefox have audio lockup bugs) - Retest this 27 | * Firefox 28+ (Web Audio API creates 500 ms or greater latency, forced by Firefox) 28 | * Opera (Crashes + Slow + Graphics Glitches) - Retest this 29 | * Safari 5.1.X (Below 5.1.5) (Slow or crashes) 30 | * IE 1-8 (Cannot run) 31 | * IE 9-10 (Slow, No native audio support (Requires flash bridge in the audio lib)) 32 | * IE 11 (No native audio support (Requires flash bridge in the audio lib)) 33 | * Firefox 1-3.6 (Slow) 34 | * ALL VERSIONS OF MOBILE SAFARI AND OPERA (Stop pestering me, iOS just **CAN'T** run this well.) 35 | 36 | CPU instruction set accuracy test results (Blargg's cpu_instrs.gb test ROM): 37 | ----------------------------------------------------- 38 | 39 | * **GameBoy Online:** 40 | 41 | ![GameBoy Online (This emulator)](http://i.imgur.com/ivs7F.png "Passes") 42 | * **Visual Boy Advance 1.7.2:** 43 | 44 | ![Visual Boy Advance 1.7.2](http://i.imgur.com/NYnYu.png "Fails") 45 | * **KiGB:** 46 | 47 | ![KiGB](http://i.imgur.com/eYHDH.png "Fails") 48 | * **Gambatte:** 49 | 50 | ![Gambatte](http://i.imgur.com/vGHFz.png "Passes") 51 | -------------------------------------------------------------------------------- /css/GameBoy.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | html { 3 | background-color: rgb(200, 225, 225); 4 | background-attachment: fixed; 5 | background-repeat: none; 6 | background-image: url("../images/gradient_01.svg"); 7 | background-image: -webkit-linear-gradient(315deg, rgb(200, 200, 255), rgb(200, 255, 200)); 8 | background-image: -moz-linear-gradient(315deg, rgb(200, 200, 255), rgb(200, 255, 200)); 9 | background-image: -o-linear-gradient(315deg, rgb(200, 200, 255), rgb(200, 255, 200)); 10 | background-image: linear-gradient(135deg, rgb(200, 200, 255), rgb(200, 255, 200)); 11 | margin: 0; 12 | padding: 0; 13 | font-family: arial; 14 | margin: 0; 15 | padding: 0; 16 | overflow: auto; 17 | text-align: left; 18 | direction: ltr; 19 | width: 100%; 20 | height: 100%; 21 | text-rendering: optimizeSpeed; 22 | } 23 | body { 24 | width: auto; 25 | height: auto; 26 | min-width: 100%; 27 | min-height: 100%; 28 | border: none; 29 | margin: 0; 30 | padding: 0; 31 | } 32 | div.menubar, div#GameBoy > div#gfx, div.window > div.button_rack, ul.menu { 33 | -webkit-text-size-adjust: none; 34 | -webkit-tap-highlight-color: transparent; 35 | -webkit-touch-callout: none; 36 | -webkit-user-select: none; 37 | -moz-user-select: none; 38 | -khtml-user-select: none; 39 | user-select: none; 40 | } 41 | div.window { 42 | visibility: visible; 43 | display: none; 44 | position: absolute; 45 | overflow: hidden; 46 | margin: 0; 47 | padding: 10px 0px 0px 0px; 48 | top: 0; 49 | left: 0; 50 | color: rgb(0, 0, 0); 51 | font-size: 16px; 52 | -webkit-border-radius: 10px 10px 3px 3px; 53 | border-radius: 10px 10px 3px 3px; 54 | -webkit-box-shadow: 5px 5px 10px rgb(30, 30, 30); 55 | box-shadow: 5px 5px 10px rgb(30, 30, 30); 56 | background-color: rgb(200, 200, 200); 57 | z-index: 2; 58 | opacity: 1; 59 | } 60 | div#GameBoy { 61 | min-height: 340px; 62 | min-width: 400px; 63 | } 64 | div#input_select, div#save_importer { 65 | min-height: 100px; 66 | min-width: 200px; 67 | } 68 | div#instructions { 69 | min-height: 300px; 70 | min-width: 400px; 71 | } 72 | div.menubar { 73 | max-height: 28px; 74 | min-width: 250px; /*Fail safe for poopy browsers.*/ 75 | display: block; 76 | overflow: hidden; 77 | position: absolute; 78 | left: 0; 79 | right: 0; 80 | border-top-style: solid; 81 | border-top-width: 1px; 82 | border-top-color: rgb(150, 150, 150); 83 | border-left-style: none; 84 | border-right-style: none; 85 | border-bottom-style: solid; 86 | border-bottom-width: 1px; 87 | border-bottom-color: rgb(50, 50, 50); 88 | text-overflow: ellipsis; 89 | margin: 0; 90 | padding: 0 0 0 3px; 91 | text-align: left; 92 | background-color: rgb(210, 210, 210); 93 | background-repeat: repeat-x; 94 | background-attachment: scroll; 95 | background-image: url("../images/gradient_02.svg"); 96 | background-image: -webkit-linear-gradient(top, rgb(150, 150, 150), rgb(220, 220, 220), rgb(180, 180, 180)); 97 | background-image: -moz-linear-gradient(top, rgb(150, 150, 150), rgb(220, 220, 220), rgb(180, 180, 180)); 98 | background-image: -o-linear-gradient(top, rgb(150, 150, 150), rgb(220, 220, 220), rgb(180, 180, 180)); 99 | background-image: linear-gradient(top, rgb(150, 150, 150), rgb(220, 220, 220), rgb(180, 180, 180)); 100 | } 101 | div.menubar > span { 102 | cursor: pointer; 103 | -webkit-border-radius: 5px; 104 | border-radius: 5px; 105 | background-color: transparent; 106 | padding: 2px 5px; 107 | margin: 3px 3px 3px 0; 108 | display: inline; 109 | display: inline-block; 110 | } 111 | div.menubar > span:hover { 112 | -webkit-box-shadow: 2px 2px 1px rgb(30, 30, 30); 113 | box-shadow: 2px 2px 1px rgb(30, 30, 30); 114 | background-color: rgb(160, 160, 160); 115 | background-repeat: repeat-x; 116 | background-attachment: scroll; 117 | background-image: url("../images/gradient_03.svg"); 118 | background-image: -webkit-linear-gradient(top, rgb(160, 160, 160), rgb(190, 190, 190), rgb(160, 160, 160)); 119 | background-image: -moz-linear-gradient(top, rgb(160, 160, 160), rgb(190, 190, 190), rgb(160, 160, 160)); 120 | background-image: -o-linear-gradient(top, rgb(160, 160, 160), rgb(190, 190, 190), rgb(160, 160, 160)); 121 | background-image: linear-gradient(top, rgb(160, 160, 160), rgb(190, 190, 190), rgb(160, 160, 160)); 122 | } 123 | div.menubar > span:active { 124 | -webkit-box-shadow: inset 2px 2px 1px rgb(30, 30, 30); 125 | box-shadow: inset 2px 2px 1px rgb(30, 30, 30); 126 | background-color: rgb(220, 220, 220); 127 | background-repeat: repeat-x; 128 | background-attachment: scroll; 129 | background-image: url("../images/gradient_04.svg"); 130 | background-image: -webkit-linear-gradient(top, rgb(190, 190, 190), rgb(160, 160, 160), rgb(190, 190, 190)); 131 | background-image: -moz-linear-gradient(top, rgb(190, 190, 190), rgb(160, 160, 160), rgb(190, 190, 190)); 132 | background-image: -o-linear-gradient(top, rgb(190, 190, 190), rgb(160, 160, 160), rgb(190, 190, 190)); 133 | background-image: linear-gradient(top, rgb(190, 190, 190), rgb(160, 160, 160), rgb(190, 190, 190)); 134 | } 135 | div#gfx { 136 | height: auto; 137 | width: auto; 138 | margin: 0; 139 | padding: 0; 140 | position: absolute; 141 | bottom: 3px; 142 | left: 3px; 143 | right: 3px; 144 | top: 43px; 145 | background-color: rgb(200, 50, 50); 146 | background-repeat: repeat-x; 147 | background-attachment: scroll; 148 | background-image: url("../images/gradient_05.svg"); 149 | background-image: -webkit-linear-gradient(top, rgb(200, 50, 50), rgb(200, 75, 150)); 150 | background-image: -moz-linear-gradient(top, rgb(200, 50, 50), rgb(200, 75, 150)); 151 | background-image: -o-linear-gradient(top, rgb(200, 50, 50), rgb(200, 75, 150)); 152 | background-image: linear-gradient(top, rgb(200, 50, 50), rgb(200, 75, 150)); 153 | } 154 | body > div#fullscreenContainer { 155 | position: absolute; /*Fallback here if fixed isn't supported*/ 156 | position: fixed; 157 | height: 100%; 158 | width: 100%; 159 | left: 0; 160 | right: 0; 161 | top: 0; 162 | bottom: 0px; 163 | background-color: rgb(0, 0, 0); 164 | display: none; 165 | z-index: 100; 166 | } 167 | body > div#fullscreenContainer > canvas#fullscreen.maximum { 168 | position: static; 169 | height: 100%; 170 | width: 100%; 171 | margin: 0; 172 | padding: 0; 173 | } 174 | body > div#fullscreenContainer > canvas#fullscreen.minimum { 175 | position: absolute; 176 | height: 144px; 177 | width: 160px; 178 | top: 50%; 179 | left: 50%; 180 | margin: -72px 0 0 -80px; 181 | padding: 0; 182 | } 183 | div#GameBoy > div#gfx > canvas { 184 | position: absolute; 185 | z-index: 5; 186 | visibility: hidden; 187 | top: 0; 188 | left: 0; 189 | right: 0; 190 | bottom: 0; 191 | width: 100%; 192 | height: 100%; 193 | background-color: rgb(255, 255, 255); 194 | } 195 | div#GameBoy > div#gfx > span#title { 196 | position: absolute; 197 | top: 30%; 198 | left: 15%; 199 | font-size: 64px; 200 | color: rgb(220, 220, 150); 201 | text-shadow: 3px 3px 5px rgb(50, 50, 50); 202 | font-style: italic; 203 | z-index: 1; 204 | padding: 0 5px 0 0; 205 | } 206 | div#GameBoy > div#gfx > span#port_title { 207 | position: absolute; 208 | top: 45%; 209 | left: 55%; 210 | font-size: 32px; 211 | color: rgb(180, 70, 70); 212 | text-shadow: 2px 2px 4px rgb(80, 80, 80); 213 | font-style: italic; 214 | font-weight: bold; 215 | z-index: 2; 216 | padding: 0 5px 0 0; 217 | } 218 | div#about { 219 | max-width: 400px; 220 | max-height: 350px; 221 | min-width: 400px; 222 | min-height: 350px; 223 | } 224 | div#terminal { 225 | min-height: 100px; 226 | min-width: 310px; 227 | } 228 | div#terminal, div#about, div#settings, div#local_storage_listing, div#freeze_listing { 229 | height: 350px; 230 | width: 400px; 231 | } 232 | div#settings { 233 | height: 410px; 234 | } 235 | div#local_storage_popup { 236 | height: 250px; 237 | width: 300px; 238 | } 239 | div#local_storage_listing, div#freeze_listing { 240 | min-width: 400px; 241 | min-height: 350px; 242 | } 243 | div.storageList { 244 | position: absolute; 245 | top: 10px; 246 | left: 3px; 247 | right: 4px; 248 | overflow: auto; 249 | text-align: left; 250 | bottom: 50px; 251 | background-color: rgb(140, 140, 140); 252 | -webkit-border-radius: 3px; 253 | border-radius: 3px; 254 | -webkit-box-shadow: inset 3px 3px 2px 1px rgb(110, 110, 110); 255 | box-shadow: inset 3px 3px 2px 1px rgb(110, 110, 110); 256 | padding: 3px; 257 | } 258 | div#storageListingMasterContainer { 259 | top: 40px !important; 260 | } 261 | div#download_all_storage { 262 | position: absolute; 263 | height: 20px; 264 | left: 3px; 265 | top: 10px; 266 | right: 4px; 267 | text-align: center; 268 | font-style: bold; 269 | background-color: rgb(140, 140, 140); 270 | -webkit-border-radius: 3px; 271 | border-radius: 3px; 272 | -webkit-box-shadow: inset 3px 3px 2px 1px rgb(110, 110, 110); 273 | box-shadow: inset 3px 3px 2px 1px rgb(110, 110, 110); 274 | padding: 3px; 275 | } 276 | div.storageList a, div#download_all_storage a { 277 | color: rgb(210, 210, 210); 278 | } 279 | div#terminal > div#terminal_output { 280 | background-color: rgb(0, 0, 0); 281 | margin: 0; 282 | padding: 0; 283 | font-family: monotype; 284 | font-size: 12px; 285 | bottom: 50px; 286 | padding: 10px; 287 | top: 10px; 288 | right: 3px; 289 | left: 3px; 290 | position: absolute; 291 | cursor: crosshair; 292 | overflow: auto; 293 | text-align: left; 294 | } 295 | div#terminal > div#terminal_output > span.white { 296 | color: rgb(255, 255, 255); 297 | } 298 | div#terminal > div#terminal_output > span.white:before { 299 | content: " "; 300 | font-weight: bold; 301 | } 302 | div#terminal > div#terminal_output > span.yellow { 303 | color: rgb(255, 255, 0); 304 | } 305 | div#terminal > div#terminal_output > span.yellow:before { 306 | content: " "; 307 | font-weight: bold; 308 | } 309 | div#terminal > div#terminal_output > span.red { 310 | color: rgb(0, 0, 255); 311 | } 312 | div#terminal > div#terminal_output > span.red:before { 313 | content: " "; 314 | font-weight: bold; 315 | } 316 | div#about > div#about_message, div#instructions > div#keycodes { 317 | position: absolute; 318 | top: 10px; 319 | left: 3px; 320 | bottom: 50px; 321 | right: 3px; 322 | background-color: rgb(230, 230, 230); 323 | border-width: 5px; 324 | border-style: groove; 325 | border-color: rgb(50, 50, 50); 326 | padding: 5px; 327 | overflow: auto; 328 | } 329 | div#about > div#about_message > h1 { 330 | font-size: 20px; 331 | color: rgb(80, 60, 20); 332 | } 333 | div#settings > div#toggle_settings { 334 | position: absolute; 335 | top: 10px; 336 | left: 3px; 337 | right: 3px; 338 | bottom: 50px; 339 | } 340 | div#settings > div#toggle_settings > div.setting { 341 | text-align: left; 342 | width: 100%; 343 | position: relative; 344 | margin: 0; 345 | padding: 0 0 3px 0; 346 | border: none; 347 | } 348 | div#settings > div#toggle_settings > div.setting:hover { 349 | border-bottom-style: dashed; 350 | border-bottom-color: rgb(70, 70, 70); 351 | border-bottom-width: 1px; 352 | } 353 | div#settings > div#toggle_settings > div.setting input { 354 | float: right; 355 | } 356 | div.window > div.button_rack { 357 | background-color: transparent; 358 | margin: 0; 359 | padding: 0; 360 | position: absolute; 361 | height: 44px; 362 | bottom: 3px; 363 | right: 3px; 364 | left: 3px; 365 | text-align: center; 366 | } 367 | div.window > div.button_rack > button { 368 | cursor: pointer; 369 | padding: 0; 370 | margin: 0; 371 | height: 44px; 372 | width: 150px; 373 | text-align: center; 374 | font-size: 14px; 375 | position: relative; 376 | } 377 | div.window > div.button_rack > button.left { 378 | float: left; 379 | } 380 | div.window > div.button_rack > button.right { 381 | float: right; 382 | } 383 | div.window > div.button_rack > button.center { 384 | width: 100%; 385 | } 386 | ul.menu { 387 | list-style-position: inside; 388 | position: absolute; 389 | display: none; 390 | list-style-type: none; 391 | width: auto; 392 | height: auto; 393 | margin: 0; 394 | padding: 0; 395 | top: 0; 396 | left: 0; 397 | z-index: 3; 398 | background-color: rgb(200, 200, 200); 399 | background-repeat: repeat-x; 400 | background-attachment: scroll; 401 | background-image: url("../images/gradient_06.svg"); 402 | background-image: -webkit-linear-gradient(left, rgb(200, 200, 200), rgb(240, 240, 240)); 403 | background-image: -moz-linear-gradient(left, rgb(200, 200, 200), rgb(240, 240, 240)); 404 | background-image: -o-linear-gradient(left, rgb(200, 200, 200), rgb(240, 240, 240)); 405 | background-image: linear-gradient(left, rgb(200, 200, 200), rgb(240, 240, 240)); 406 | -webkit-border-radius: 3px; 407 | border-radius: 3px; 408 | -webkit-box-shadow: 5px 5px 10px rgb(30, 30, 30); 409 | box-shadow: 5px 5px 10px rgb(30, 30, 30); 410 | border-style: solid; 411 | border-top-width: 1px; 412 | border-left-width: 1px; 413 | border-right-width: 2px; 414 | border-bottom-width: 2px; 415 | border-top-color: rgb(100, 100, 100); 416 | border-left-color: rgb(100, 100, 100); 417 | border-bottom-color: rgb(50, 50, 50); 418 | border-right-color: rgb(50, 50, 50); 419 | overflow: visible; 420 | } 421 | ul.menu:hover { 422 | display: block; 423 | display: inline-block; 424 | top: 0; 425 | left: 0; 426 | } 427 | ul.menu > li { 428 | display: block; 429 | position: relative; 430 | margin: 0 0 -1px 0; /*Firefox DOM mouseover bug*/ 431 | padding: 2px 5px 2px 15px; 432 | color: rgb(0, 0, 0); 433 | background-color: transparent; 434 | width: 200px; 435 | height: auto; 436 | border: none; 437 | overflow: visible; 438 | text-overflow: ellipsis; 439 | } 440 | ul.menu > li:hover { 441 | background-color: transparent; 442 | background-color: rgb(255, 255, 200); 443 | background-color: rgba(255, 255, 200, 0.3); 444 | } 445 | ul.menu > li:hover > ul.menu { 446 | left: 220px; 447 | top: 0; 448 | display: block; 449 | display: inline-block; 450 | } -------------------------------------------------------------------------------- /css/mobile.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | width: 100%; 5 | height: 100%; 6 | background-color: black; 7 | font-family: Verdana; 8 | } 9 | 10 | #gameboy_shell { 11 | height: 100%; 12 | min-height: 480px; 13 | min-width: 320px; 14 | border-top-left-radius: 15px; 15 | border-top-right-radius: 15px; 16 | border-bottom-left-radius: 15px; 17 | border-bottom-right-radius: 45px; 18 | box-shadow: inset -15px 16px 6px -12px rgba(255,255,255, 0.5), inset 15px -11px 6px -11px rgba(0,0,0,0.5); 19 | } 20 | 21 | #on_off { 22 | margin-left: 10%; 23 | font-size: 10pt; 24 | text-shadow: 0px 0px 2px #000; 25 | } 26 | 27 | #screen_cover { 28 | background-color: #525E59; 29 | width: 80%; 30 | height: 40%; 31 | margin: 0 auto; 32 | border: 1px solid black; 33 | border-top-left-radius: 5px; 34 | border-top-right-radius: 5px; 35 | border-bottom-left-radius: 5px; 36 | border-bottom-right-radius: 30px; 37 | } 38 | 39 | #power { 40 | float: left; 41 | position: relative; 42 | top: 30%; 43 | font-size: 8pt; 44 | color: white; 45 | padding-left: 5px; 46 | } 47 | 48 | .two_column { 49 | width: 30px; 50 | height: 15px; 51 | } 52 | 53 | #power_light { 54 | float: left; 55 | position: static; 56 | width: 10px; 57 | height: 10px; 58 | background-color: red; 59 | margin-left: 5px; 60 | margin-top: 2px; 61 | border-radius: 10px; 62 | } 63 | 64 | #power_light +div { 65 | float: right; 66 | } 67 | 68 | #canvas_container { 69 | width: 160px; 70 | margin: 20px auto 0 auto; 71 | } 72 | 73 | #screen_cover > div:last-child { 74 | position: relative; 75 | left: 15%; 76 | width: 120px; 77 | font-size: 10pt; 78 | text-align: center; 79 | color: white; 80 | font-style: oblique; 81 | } 82 | 83 | #pocket { 84 | color: #525E59; 85 | background-color: white; 86 | font-size: 8pt; 87 | } 88 | 89 | #nintendo { 90 | border-radius: 10px; 91 | width: 25%; 92 | text-align: center; 93 | margin: 10px auto 0 auto; 94 | padding: 0 5px; 95 | text-shadow: 0px 0px 2px #000; 96 | box-shadow: 0px 0px 2px #000, inset 0px 0px 2px #000; 97 | } 98 | 99 | #d_pad { 100 | width: 70px; 101 | height: 70px; 102 | position: relative; 103 | top: 20px; 104 | left: 10%; 105 | } 106 | 107 | #d_pad > div { 108 | background-color: #525E59; 109 | } 110 | 111 | #d_pad_up { 112 | box-shadow: inset -15px 10px 10px -12px rgba(255,255,255, 0.5), inset 15px -11px 6px -11px rgba(0,0,0,0.5); 113 | border-top-left-radius: 5px; 114 | border-top-right-radius: 5px; 115 | width: 33%; 116 | height: 33%; 117 | margin: 0 auto; 118 | } 119 | 120 | #d_pad_left_right { 121 | box-shadow: inset -15px 10px 10px -12px rgba(255,255,255, 0.5), inset 15px -11px 6px -11px rgba(0,0,0,0.5); 122 | border-radius: 5px; 123 | height: 33%; 124 | margin: 0 auto; 125 | } 126 | 127 | #d_pad_down { 128 | box-shadow: inset -15px 10px 10px -12px rgba(255,255,255, 0.5), inset 15px -11px 6px -11px rgba(0,0,0,0.5); 129 | border-bottom-left-radius: 5px; 130 | border-bottom-right-radius: 5px; 131 | width: 33%; 132 | height: 33%; 133 | margin: 0 auto; 134 | } 135 | 136 | #d_pad_left { 137 | width: 33%; 138 | height: 100%; 139 | float: left; 140 | } 141 | 142 | #d_pad_center { 143 | border: 1px solid black; 144 | height: 20px; 145 | width: 20px; 146 | margin: 0 auto; 147 | border-radius: 20px; 148 | /*box-shadow: inset 5px -5px 6px 0px rgba(255,255,255, 0.5);*/ 149 | box-shadow: inset -15px 10px 10px -12px rgba(0,0,0, 0.5), inset 15px -11px 6px -11px rgba(255,255,255,0.5); 150 | } 151 | 152 | #d_pad_right { 153 | width: 33%; 154 | height: 100%; 155 | float: right; 156 | } 157 | 158 | #arrow_up, #arrow_down, #arrow_left, #arrow_right { 159 | width: 0; 160 | height: 0; 161 | margin: 0 auto; 162 | } 163 | 164 | #arrow_up { 165 | border-left: 10px solid transparent; 166 | border-right: 10px solid transparent; 167 | border-bottom: 20px solid black; 168 | } 169 | 170 | #arrow_left { 171 | border-top: 10px solid transparent; 172 | border-right: 20px solid black; 173 | border-bottom: 10px solid transparent; 174 | } 175 | 176 | #arrow_right { 177 | border-left: 20px solid black; 178 | border-top: 10px solid transparent; 179 | border-bottom: 10px solid transparent; 180 | } 181 | #arrow_down { 182 | border-left: 10px solid transparent; 183 | border-right: 10px solid transparent; 184 | border-top: 20px solid black; 185 | } 186 | 187 | #a_button_group { 188 | left: 75%; 189 | top: 55%; 190 | } 191 | 192 | #b_button_group { 193 | left: 55%; 194 | top: 60%; 195 | } 196 | 197 | #select_button_group { 198 | left: 33%; 199 | top: 85%; 200 | } 201 | 202 | #start_button_group { 203 | right: 33%; 204 | top: 85% 205 | } 206 | 207 | .button_group { 208 | position: absolute; 209 | text-align: center; 210 | color: #525E59; 211 | font-size: 10pt; 212 | } 213 | 214 | .button_group div { 215 | width: 40px; 216 | background-color: #525E59; 217 | border-radius: 20px; 218 | margin: 0 auto 10px auto; 219 | box-shadow: inset -15px 10px 10px -12px rgba(255,255,255, 0.5), inset 15px -11px 6px -11px rgba(0,0,0,0.5); 220 | } 221 | 222 | .button_group .round_button { 223 | height: 40px; 224 | } 225 | 226 | .button_group .flat_button { 227 | height: 15px; 228 | } 229 | 230 | #speaker { 231 | position: relative; 232 | left: 70%; 233 | top: 15%; 234 | } 235 | -------------------------------------------------------------------------------- /images/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisel/GameBoy-Online/47f9f638a8a9445aaa75050f634e437baa34aae0/images/128.png -------------------------------------------------------------------------------- /images/gradient_01.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/gradient_02.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /images/gradient_03.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /images/gradient_04.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /images/gradient_05.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/gradient_06.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/speaker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisel/GameBoy-Online/47f9f638a8a9445aaa75050f634e437baa34aae0/images/speaker.png -------------------------------------------------------------------------------- /index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | --------------------------------------------------------------------------------