SlideShare a Scribd company logo
Emulating with
  JavaScript

    new Cpu;
WHOAMI
WHOAMI

• Alexander Dickson
WHOAMI

• Alexander Dickson
• @alexdickson
WHOAMI

• Alexander Dickson
• @alexdickson
• Not an emulation expert
WHOAMI

• Alexander Dickson
• @alexdickson
• Not an emulation expert
• JavaScript developer at Atlassian
WHOAMI

• Alexander Dickson
• @alexdickson
• Not an emulation expert
• JavaScript developer at Atlassian

                                  ;
JavaScript today
JavaScript today

• Fast
JavaScript today

• Fast
• Browser APIs are awesome
JavaScript today

• Fast
• Browser APIs are awesome
• Inputs and outputs are awesome
What we have
What we have

• Canvas Element
What we have

• Canvas Element
• Web Audio API
What we have

• Canvas Element
• Web Audio API
• GamePad API
What we have

• Canvas Element
• Web Audio API
• GamePad API
• Typed Arrays
What we have

• Canvas Element
• Web Audio API
• GamePad API
• Typed Arrays
• requestAnimationFrame()
What we don’t have
What we don’t have


• Sane implementations
What we don’t have


• Sane implementations
• Just kidding, but some are better than
  others
What we can build
What we can build


• Lots of awesome, practical stuff...
What we can build


• Lots of awesome, practical stuff...
• ...or, emulate hardware, such as gaming
  consoles.
Why?
Why?




Because we can!
What is an
emulator?
What is an
                  emulator?

  In computing, an emulator is hardware or software or both that
  duplicates (or emulates) the functions of a first computer system (the
  guest) in a different second computer system (the host), so that the
  emulated behaviour closely resembles the behaviour of the real
  system.

http://en.wikipedia.org/wiki/Emulator
What can be emulated
What can be emulated


• Church-Turing thesis
What can be emulated


• Church-Turing thesis
• Any system can be emulated
Implementations
Implementations




• Interpreter
Implementations




• Interpreter
• Dynamic Re-compilation
Implementations




• Interpreter
• Dynamic Re-compilation
• Static Re-compilation
Shhhh...
Shhhh...

• Emulation can sometimes be a bit shaky
  from a legal perspective.
Shhhh...

• Emulation can sometimes be a bit shaky
  from a legal perspective.
• Emulate at your own risk and always use
  free programs.
Shhhh...

• Emulation can sometimes be a bit shaky
  from a legal perspective.
• Emulate at your own risk and always use
  free programs.
Where to start

      CPU
Where to start

• Pick a system, anyCPU
                     system
Where to start

• Pick a system, anyCPU
                     system
• Discover its components
Where to start

• Pick a system, anyCPU
                      system
• Discover its components
• Find technical information on how
  components work
Chip8
Chip8 is Easy
Chip8 is Easy

• Simple CPU implementation
Chip8 is Easy

• Simple CPU implementation
• Simple graphics
Chip8 is Easy

• Simple CPU implementation
• Simple graphics
• Fixed audio sample
Demo Time
Example System
Emulating With JavaScript
Nintendo Entertainment System
Nintendo Entertainment System


• Custom 6502 CPU
Nintendo Entertainment System


• Custom 6502 CPU
• 2KiB onboard RAM, 2KiB video RAM, 256B
  OAM RAM, 28B palette RAM
Nintendo Entertainment System


• Custom 6502 CPU
• 2KiB onboard RAM, 2KiB video RAM, 256B
  OAM RAM, 28B palette RAM
• Custom-made PPU
Nintendo Entertainment System


• Custom 6502 CPU
• 2KiB onboard RAM, 2KiB video RAM, 256B
  OAM RAM, 28B palette RAM
• Custom-made PPU
• 5 sound channels
Nintendo Entertainment System


• Custom 6502 CPU
• 2KiB onboard RAM, 2KiB video RAM, 256B
  OAM RAM, 28B palette RAM
• Custom-made PPU
• 5 sound channels
• Awesome rectangular controllers
Von-Neumann
 Architecture

CPU                 Memory


        Bus



      Peripherals
CPU
CPU

• Basically a loop
CPU

• Basically a loop
• Read operation codes (opcodes) from
  memory, processes them
CPU

• Basically a loop
• Read operation codes (opcodes) from
  memory, processes them
• Opcodes mostly operate on registers
6502
6502
•   Ricoh 2A03/2A07, customised 6502 w/ audio w/
    gamepad w/o BCD
6502
•   Ricoh 2A03/2A07, customised 6502 w/ audio w/
    gamepad w/o BCD

•   8 bit processor w/ 16 bit address bus
6502
•   Ricoh 2A03/2A07, customised 6502 w/ audio w/
    gamepad w/o BCD

•   8 bit processor w/ 16 bit address bus

•   1-2MHz clock speed
6502
•   Ricoh 2A03/2A07, customised 6502 w/ audio w/
    gamepad w/o BCD

•   8 bit processor w/ 16 bit address bus

•   1-2MHz clock speed

•   http://www.6502.org/documents/datasheets/
    rockwell/
// Customised 6502 CPU
Nes.Cpu = function() {
    this.registers = {
        // Program Counter (16bit)
        pc: null,
        // Stack Pointer (8bit)
        sp: null,
        // Accumulator (8bit)
        a: null,
        // Index X (8bit)
        x: null,
        // Index Y (8bit)
        y: null,
        // Processor Status,
        p: null
    };
	 // ...
    this.reset();
};
Memory
Memory


• Contiguous block of data
Memory


• Contiguous block of data
• ROM (readable)/RAM (readable/writable)
NES Memory
NES Memory
• 2KiB onboard
NES Memory
• 2KiB onboard
• Internally stored zero-page, stack, general
  purpose memory
NES Memory
• 2KiB onboard
• Internally stored zero-page, stack, general
  purpose memory
• Addressable up to 0x10000
NES Memory
• 2KiB onboard
• Internally stored zero-page, stack, general
  purpose memory
• Addressable up to 0x10000
• Program ROM contain opcodes, graphics
  and sound
Typed Arrays
Typed Arrays

• TypedArrays help performance critical
  applications such as emulators
Typed Arrays

• TypedArrays help performance critical
  applications such as emulators
• Makes it trivial to reach any specified offset
Typed Arrays

• TypedArrays help performance critical
  applications such as emulators
• Makes it trivial to reach any specified offset
• http://www.khronos.org/registry/
  typedarray/specs/latest/
Nes.Cpu = function() {
	 // ...
	 // Our device has 2KiB of RAM.
	 var memoryBuffer = new ArrayBuffer(0x800);
	 // 6502 is a 8 bit processor, able
	 // to address 8 bits at once.
	 this.memory = new Uint8Array(memory);
	 // ...
};
Need Getters/Setters



Memory is mapped everywhere, so you need to
delegate reads and writes to different areas.
Fetch/Decode Loop
Fetch/Decode Loop


• Check for interrupts
Fetch/Decode Loop


• Check for interrupts
• Read memory at PC
Fetch/Decode Loop


• Check for interrupts
• Read memory at PC
• Decode addressing mode
Fetch/Decode Loop


• Check for interrupts
• Read memory at PC
• Decode addressing mode
• Process opcode
Interrupts
Interrupts

• Special signal that interrupts normal
  execution
Interrupts

• Special signal that interrupts normal
  execution
• Loads special address into PC and executes
  it
Nes.Cpu = function() {
	 // ...
	 // Interrupt Types.
	 this.interruptTypes = {
	 	 NMI: 0
	 	 // ...
	 };
	 // Current Interrupt.
	 this.interrupt = null;
	 // ...
};

Nes.Cpu.prototype.emulateCycle = function() {
	 if (this.interrupt != null) {
	 	 switch (this.interrupt) {
	 	 	 // Non-Maskable
	 	 	 case this.interruptTypes.NMI:
	 	 	 	 this.handleNmi();
	 	 	 	 break;
	 	 	 // ...
	 	 }
	 }
	 // ...
};
Slow
Nes.Cpu.prototype.emulateCycle = function() {
    this.interrupt != null &&
    this["handle" +
         (["nmi", "irq", "reset"]
           .filter(function(type, index) {
               return index == this.interrupt;
           })[0])
        ]();
    // ...
};
Handling Opcodes
Handling Opcodes

• Read location in PC from memory
Handling Opcodes

• Read location in PC from memory
• Lookup opcode
Handling Opcodes

• Read location in PC from memory
• Lookup opcode
• Find addressing mode
Handling Opcodes

• Read location in PC from memory
• Lookup opcode
• Find addressing mode
• Process opcode
Handling Opcodes

• Read location in PC from memory
• Lookup opcode
• Find addressing mode
• Process opcode
• Increment PC
Cpu.prototype.emulateCycle = function() {
	 // ...
	 // Get opcode at PC.
	 var opcode = this.getOpcode(this.loadMemory(this.pc));
	 var address;
	
	 // Get final address via addressing mode of opcode.
	 switch (opcode.addressingMode) {
	 	 // Zero Page
	 	 // Uses a single operand which address
	 	 // memory in zero page (0x0000-0x00FF).
	 	 case this.addressingModes.ZERO_PAGE:
	 	 	 address = this.loadMemory(this.pc + 1);
	 	 	 break;
	 }
	
	 this.pc += opcode.bytes;
	 // ...
};
Process All The Opcodes
Process All The Opcodes


• Read technical paper twice, implement
  once
Process All The Opcodes


• Read technical paper twice, implement
  once
• Debugging is hard, so get it right
Process All The Opcodes


• Read technical paper twice, implement
  once
• Debugging is hard, so get it right
• When you don’t get it right, try again
Nes.Cpu.prototype.emulateCycle = function() {
	 // ...
	 switch (opcode.type) {
	 	 // JMP
	 	 // Jump to location.
	 	 case this.operands.JMP:
	 	 	 this.pc = address;
	 	 	 break;
	 }
	 // ...
};
PPU
PPU


• Generates video signals from memory
PPU


• Generates video signals from memory
• Handles sprites, scrolling, colours
RP2C02
RP2C07
RP2C02
              RP2C07

• Different chip for NTSC/PAL
RP2C02
              RP2C07

• Different chip for NTSC/PAL
• 2KiB RAM
RP2C02
              RP2C07

• Different chip for NTSC/PAL
• 2KiB RAM
• 8x8 or 8x16 sprites
RP2C02
              RP2C07

• Different chip for NTSC/PAL
• 2KiB RAM
• 8x8 or 8x16 sprites
• Resolution of 256x240
Communicating with your PPU
Communicating with your PPU



• 0x2000-0x2007 on CPU memory map to
  PPU’s registers
Communicating with your PPU



• 0x2000-0x2007 on CPU memory map to
  PPU’s registers
• 8x8 or 8x16 pixel tiles, accessed on
  program ROM
Colour Palette

• 52 colours available
• 2 palettes, 16b each, image and sprite
• Can use 25 colours at once on screen
TileS
TileS

• Each 8x8 tile occupies 16b
TileS

• Each 8x8 tile occupies 16b
• Position of bit denotes position of pixel
TileS

• Each 8x8 tile occupies 16b
• Position of bit denotes position of pixel
• First 8 bits combine with second 8 bits
TileS

• Each 8x8 tile occupies 16b
• Position of bit denotes position of pixel
• First 8 bits combine with second 8 bits
• Combine bits to get colour index
Anatomy of a tile
  1   1   1   1   1   1   1   1

  1   1   1   1   1   1   1   1

  1   1   0   1   1   0   0   1

  1   1   0   1   0   1   1   1

  1   1   0   1   1   0   1   1

  1   1   0   1   1   1   0   1

  1   0   0   1   0   0   1   1

  1   1   1   1   1   1   1   1
Anatomy of a tile
  1   1   1    1      1     1   1   1

  1   1   1    1      1     1   1   1

  1   1   0    1      1     0   0   1

  1   1   0    1      0     1   1   1

  1   1   0    1      1     0   1   1

  1   1   0    1      1     1   0   1

  1   0   0    1      0     0   1   1

  1   1   1    1      1     1   1   1


              (simplified)
Nametables
Nametables


• Bytes which index pattern table
Nametables


• Bytes which index pattern table
• 32 horizontal and 30 vertical tiles, 960 tiles
Nametables


• Bytes which index pattern table
• 32 horizontal and 30 vertical tiles, 960 tiles
• 1KiB long, delta contains extra colour
  information
Nothing is wasted
Nothing is wasted
• Remaining 64b stores extra colour
  information (attribute bytes)
Nothing is wasted
• Remaining 64b stores extra colour
  information (attribute bytes)
• Attribute bytes map to 16 tiled blocks of
  nametable (64 32x32 pixel tiles)
Nothing is wasted
• Remaining 64b stores extra colour
  information (attribute bytes)
• Attribute bytes map to 16 tiled blocks of
  nametable (64 32x32 pixel tiles)
• Each of these blocks is sub-blocked into 4
  tiles (4 16x16 pixel tiles)
Nothing is wasted
• Remaining 64b stores extra colour
  information (attribute bytes)
• Attribute bytes map to 16 tiled blocks of
  nametable (64 32x32 pixel tiles)
• Each of these blocks is sub-blocked into 4
  tiles (4 16x16 pixel tiles)
• Sub blocks affected by 2 bits from attribute
  bytes
Put it all together
  0. 1    0    1    1 0 0 1 1
  8. 0    0    1    0 1 0 0 1
960. 1    1    0    0 0 0 1 1
=============================
     1110 1100 0011 ...
=============================
Put it all together
  0. 1    0    1    1 0 0 1 1
  8. 0    0    1    0 1 0 0 1
960. 1    1    0    0 0 0 1 1
=============================
     1110 1100 0011 ...
=============================
Put it all together
  0. 1    0    1    1 0 0 1 1
  8. 0    0    1    0 1 0 0 1
960. 1    1    0    0 0 0 1 1
=============================
     1110 1100 0011 ...
=============================
Put it all together
  0. 1    0    1    1 0 0 1 1
  8. 0    0    1    0 1 0 0 1
960. 1    1    0    0 0 0 1 1
=============================
     1110 1100 0011 ...
=============================
// Byte   at offset 0.
var a =   0xB3;
// Byte   at offset 8.
var b =   0x29;
// Byte   at offset 960.
var c =   0xC3;

var merged = (a & 0x80) >> 0x6;
merged |= b >> 0x7;
merged |= (c & 0x3) << 0x2;
Scratching the surface
Scratching the surface



• There is a whole lot more going on
Scratching the surface



• There is a whole lot more going on
• http://wiki.nesdev.com/w/index.php/PPU
Emulating With JavaScript
Full Screen API
Full Screen API

• Look ma, no chrome
Full Screen API

• Look ma, no chrome
• Still want Chrome for performance
Full Screen API

• Look ma, no chrome
• Still want Chrome for performance
• https://developer.mozilla.org/en-US/docs/
  DOM/Using_fullscreen_mode
var goFullScreen = (function() {
    // Polyfills for cross browser support.
    return function(element, callback) {
        typeof callback != "function" && (callback = function() {});
        var requestFullScreen = getFullScreenMethod(element);

         if (requestFullScreen) {
             requestFullScreen = requestFullScreen.call(element);
         } else {
             return false;
         }

         document.addEventListener(fullScreenEvent, function() {
             callback.call(this, getFullScreenElement());
         });
    };
})();
Demo Time
Sound
Sound
• Vibration of air
Sound
• Vibration of air
• Represented as waves w/ freq. and
  amplitude
Sound
• Vibration of air
• Represented as waves w/ freq. and
  amplitude
• Frequency is number of phase changes per
  second
Sound
• Vibration of air
• Represented as waves w/ freq. and
  amplitude
• Frequency is number of phase changes per
  second
• Amplitude is volume of the wave measured
  in dB
NES Sound
NES Sound

• 5 sound channels
NES Sound

• 5 sound channels
• 2 pulse wave channels of variable duty cycle
NES Sound

• 5 sound channels
• 2 pulse wave channels of variable duty cycle
• 16 volume levels
NES Sound

• 5 sound channels
• 2 pulse wave channels of variable duty cycle
• 16 volume levels
• Pitch bending
Emulating With JavaScript
Emulating With JavaScript
APU
APU

• APU registers mapped to CPU memory
  starting at 0x4000
APU

• APU registers mapped to CPU memory
  starting at 0x4000
• 2 pulse-wave channels, 1 triangle-wave
  channel, 1 random-wave channel and 1
  digital channel
PULSE Wave
0x4000. 1011 1111


0x4002. 0001 0111


0x4003. 0000 0001
PULSE Wave
0x4000. 1011 1111   Volume



0x4002. 0001 0111


0x4003. 0000 0001
PULSE Wave
0x4000. 1011 1111      Volume



                    Low order bits
0x4002. 0001 0111    of raw period



0x4003. 0000 0001
PULSE Wave
0x4000. 1011 1111      Volume



                    Low order bits
0x4002. 0001 0111    of raw period


                    High order bits
0x4003. 0000 0001   of raw period
PULSE Wave
0x4000. 1011 1111                         Volume



                                       Low order bits
0x4002. 0001 0111                       of raw period
round(111860.8 / 0x117) - 1) = 400hz

                                       High order bits
0x4003. 0000 0001                      of raw period
Demo Time
Web Audio API
Web Audio API

• Based on Audio Routes
Web Audio API

• Based on Audio Routes
• Connect nodes to each other
Web Audio API

• Based on Audio Routes
• Connect nodes to each other
• Perfect for emulator sound
var gainNode = ctx.createGainNode();
gainNode.gain.value = volume;

var osc = ctx.createOscillator();
osc.connect(gainNode);
osc.type = type;
osc.frequency.value = frequency;

gainNode.connect(ctx.destination);
osc.noteOn(0);

setTimeout(function () {
    osc.noteOff(0);
}, duration);
Demo Time
Sounds good
Sounds good

• Again, scratching the surface
Sounds good

• Again, scratching the surface
• Sound information is rarer to find
Sounds good

• Again, scratching the surface
• Sound information is rarer to find
• http://wiki.nesdev.com/w/index.php/APU
Controller
Controller


• Two controllers, mapped to CPU memory
  at 0x4016 and 0x4017
Controller


• Two controllers, mapped to CPU memory
  at 0x4016 and 0x4017
• When written to, controller’s state is
  stored in sequential 8 bytes, as low order
  bit
Gamepad API
Gamepad API


• Firefox has an event based system
Gamepad API


• Firefox has an event based system
• WebKit requires polling
// Support gamepads in WebKit.
var GamePad = function(callback) {
	 if (typeof callback != "function") {
	 	 throw Error("Callback must implement [[call]].");
	 }
	 this.callback = callback;
	 this.running = false;
};

GamePad.prototype.start = function() {
    this.running = true;
    this.tick();
};

GamePad.prototype.stop = function() {
    this.running = false;
};

GamePad.prototype.tick = function() {
    if ( ! this.running) {
    	 return;
    }
	 this.callback(navigator.webkitGetGamepads());
    webkitRequestAnimationFrame(this.tick.bind(this));
};
Demo Time
Cycles
Cycles

• Components IRL run in parallel
Cycles

• Components IRL run in parallel
• Count cycles, use to sync other
  components
Cycles

• Components IRL run in parallel
• Count cycles, use to sync other
  components
• Try using Web Workers
Your very own emulator
Your very own emulator


• Spend a lot of time researching
Your very own emulator


• Spend a lot of time researching
• Start programming your own programs
Your very own emulator


• Spend a lot of time researching
• Start programming your own programs
• http://skilldrick.github.com/easy6502/
Your very own emulator


• Spend a lot of time researching
• Start programming your own programs
• http://skilldrick.github.com/easy6502/
• http://www.6502.org/books
Getting Started
Getting Started


      C8IYF
Getting Started


          C8IYF
  (Chip-8 Is Your Friend)
Tips
Tips

• JavaScript as you would C
Tips

• JavaScript as you would C
• Optimise passing around data
Tips

• JavaScript as you would C
• Optimise passing around data
• Know about V8 optimisations
Tips

• JavaScript as you would C
• Optimise passing around data
• Know about V8 optimisations
• Write your own programs
Possibilities
Possibilities


• Multiplayer via WebSockets
Possibilities


• Multiplayer via WebSockets
• Vibration API for force feedback
Possibilities


• Multiplayer via WebSockets
• Vibration API for force feedback
• File API and application cache for portable
  offline emulators
Possibilities


• Multiplayer via WebSockets
• Vibration API for force feedback
• File API and application cache for portable
  offline emulators
• localStorage for battery backed saved state
Thank You
Thank You


Questions

More Related Content

What's hot (20)

PPT
Device tree support on arm linux
Chih-Min Chao
 
PDF
Kernel Recipes 2017 - The Serial Device Bus - Johan Hovold
Anne Nicolas
 
PDF
Videogame Optimization
Amir H. Fassihi
 
PDF
Kernel Recipes 2017 - What's inside the input stack? - Benjamain Tissoires
Anne Nicolas
 
PPTX
Tech Days 2015: Embedded Product Update
AdaCore
 
PDF
Capturing Stills, Sounds, and Scenes with AV Foundation
Chris Adamson
 
PPT
Kgdb kdb modesetting
Kaushal Kumar Gupta
 
PDF
Linux Kernel Live Patching
GlobalLogic Ukraine
 
PPTX
Animation Programming Techniques
Amir H. Fassihi
 
PDF
LCA2018 Open Hardware MiniConference: LoliBot Software
Andy Gelme
 
PDF
Lets Play Together
Amir H. Fassihi
 
PDF
BSidesDelhi 2018: Headshot - Game Hacking on macOS
BSides Delhi
 
PDF
Linux Kernel Platform Development: Challenges and Insights
GlobalLogic Ukraine
 
PPTX
Raspberry Pi Gaming Rig
Duc Le
 
PDF
XenSummit NA 2012: Xen on ARM Cortex A15
The Linux Foundation
 
PDF
IPv6 Fundamentals & Securities
Don Anto
 
PDF
Polstra 44con2012
Philip Polstra
 
PDF
Porting Android
Opersys inc.
 
PDF
Device tree
Rouyun Pan
 
PDF
From SaltStack to Puppet and beyond...
Yury Bushmelev
 
Device tree support on arm linux
Chih-Min Chao
 
Kernel Recipes 2017 - The Serial Device Bus - Johan Hovold
Anne Nicolas
 
Videogame Optimization
Amir H. Fassihi
 
Kernel Recipes 2017 - What's inside the input stack? - Benjamain Tissoires
Anne Nicolas
 
Tech Days 2015: Embedded Product Update
AdaCore
 
Capturing Stills, Sounds, and Scenes with AV Foundation
Chris Adamson
 
Kgdb kdb modesetting
Kaushal Kumar Gupta
 
Linux Kernel Live Patching
GlobalLogic Ukraine
 
Animation Programming Techniques
Amir H. Fassihi
 
LCA2018 Open Hardware MiniConference: LoliBot Software
Andy Gelme
 
Lets Play Together
Amir H. Fassihi
 
BSidesDelhi 2018: Headshot - Game Hacking on macOS
BSides Delhi
 
Linux Kernel Platform Development: Challenges and Insights
GlobalLogic Ukraine
 
Raspberry Pi Gaming Rig
Duc Le
 
XenSummit NA 2012: Xen on ARM Cortex A15
The Linux Foundation
 
IPv6 Fundamentals & Securities
Don Anto
 
Polstra 44con2012
Philip Polstra
 
Porting Android
Opersys inc.
 
Device tree
Rouyun Pan
 
From SaltStack to Puppet and beyond...
Yury Bushmelev
 

Similar to Emulating With JavaScript (20)

PPTX
ROM Hacking for Fun, Profit & Infinite Lives
Ulisses Albuquerque
 
PDF
Build your own NES Emulator... with Kotlin
Artur Skowroński
 
PDF
Atari 2600 VCS Programming
Carlos Duarte do Nascimento
 
PPTX
Alessandro Abbruzzetti - Kernal64
Scala Italy
 
PDF
Expanding The Micro Blaze System
iuui
 
PDF
Copy Protection Wars: Analyzing Retro and Modern Schemes (RSA 2007)
Nate Lawson
 
PPSX
Retrobjects - Fun with C64 and NES
ESUG
 
PDF
Music player case study using C++ and others
simonoct8
 
PDF
Music player case study using C++ and others 2
simonoct8
 
PPTX
Intro (lesson1)comp arch
Roger Duran
 
PPT
Mcu51
EngrShoaib
 
PPTX
CST 20363 Session 4 Computer Logic Design
oudesign
 
PDF
6502 in action
Luis Vasquez
 
PPTX
internal components Technical
harrison96
 
PPT
Computer architecture
Rishabha Garg
 
PPTX
.net for fun: write a Christmas videogame
Marco Parenzan
 
PPT
glitchNES - Bent Fest workshop
nocarrier
 
PPT
AVR Fundamentals
Vinit Vyas
 
PDF
Emulating Game Boy in Java
Tomasz Rękawek
 
PDF
Brief History of Graphics Devices
Tat Iwamoto
 
ROM Hacking for Fun, Profit & Infinite Lives
Ulisses Albuquerque
 
Build your own NES Emulator... with Kotlin
Artur Skowroński
 
Atari 2600 VCS Programming
Carlos Duarte do Nascimento
 
Alessandro Abbruzzetti - Kernal64
Scala Italy
 
Expanding The Micro Blaze System
iuui
 
Copy Protection Wars: Analyzing Retro and Modern Schemes (RSA 2007)
Nate Lawson
 
Retrobjects - Fun with C64 and NES
ESUG
 
Music player case study using C++ and others
simonoct8
 
Music player case study using C++ and others 2
simonoct8
 
Intro (lesson1)comp arch
Roger Duran
 
Mcu51
EngrShoaib
 
CST 20363 Session 4 Computer Logic Design
oudesign
 
6502 in action
Luis Vasquez
 
internal components Technical
harrison96
 
Computer architecture
Rishabha Garg
 
.net for fun: write a Christmas videogame
Marco Parenzan
 
glitchNES - Bent Fest workshop
nocarrier
 
AVR Fundamentals
Vinit Vyas
 
Emulating Game Boy in Java
Tomasz Rękawek
 
Brief History of Graphics Devices
Tat Iwamoto
 
Ad

Recently uploaded (20)

PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PDF
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
Using FME to Develop Self-Service CAD Applications for a Major UK Police Force
Safe Software
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PPTX
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
Using FME to Develop Self-Service CAD Applications for a Major UK Police Force
Safe Software
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
Ad

Emulating With JavaScript

Editor's Notes