Emulating a
6502 system

(in Javascript)

Matt Godbolt

Emulating a
6502 system

(in Javascript)

Matt Godbolt

The 6502

6502 Computers

What's a BBC Micro?

Why me?

Why me?

Why Javascript?

6502 101

Instructions


LDA STA LDX ... ; load / store A, X, Y
TAX TXA ...     ; transfer A to X
PHA PLA         ; push A / pull A
CMP             ; compare with A
ADC SBC         ; add/subtract with carry
CLC SEC         ; clear / set carry
JMP             ; jump
BEQ BNE BCC BCS ; branch ==, !=, carry set/clear
BMI BPL ...     ; <0, >=0
JSR             ; jump to subroutine
RTS             ; return from subroutine
                     

Addressing modes


a9 20     LDA #$20     ; A = 0x20

a5 70     LDA $70      ; A = readmem(0x70)

ad 34 12  LDA $1234    ; A = readmem(0x1234)
                     

Addressing modes


bd 34 12  LDA $1234, X ; A = readmem(0x1234 + X)
b9 34 12  LDA $1234, Y ; A = readmem(0x1234 + Y)

b1 70     LDA ($70), Y ; t1 = readmem(0x70)
                       ; t2 = readmem(0x71)
                       ; addr = t1 | (t2<<8)
                       ; A = readmem(addr + Y)

b5 70     LDA $70, X   ; A = readmem(0x70 + X)
                     

Emulating a 6502

  • Fetch next instruction
  • Decode it
  • Execute it

Emulation


var a = 0, x = 0, y = 0;
var pc = readword(0xfffe);
while (true) {
  switch (readmem(pc++)) {
  case 0xa9: a = readmem(pc++); break; // LDA #imm
  case 0xa3: // LDA $addr
    var addr = readword(pc); pc += 2;
    a = readmem(addr);
    break;
  // and so on for all other instructions...
  }
}

The outside world

  • Memory-mapped I/O
  • Video chip:
    • Pixel generator reads from RAM
    • Simple character-mapped mode
    • Bitmap modes with 2, 4, 16 colours
  • Timers
  • Sound, etc

Demo

What happened?

Fixing it


case 0xa9: // LDA #imm
  a = readmem(pc++);
  video.run(2);
  timers.run(2);
  break;
                     

Demo

More games

Zalaga

Inside the 6502

    $84 10000100 STY zp
    $85 10000101 STA zp
    $86 10000110 STX zp
    $87 10000111 ???

Real decoding

©2010 Visual6502.org, used with permission

Inside the 6502

    $84 10000100 STY zp
    $85 10000101 STA zp
    $86 10000110 STX zp
    $87 10000111 SAX zp

Even more games

An admission

Protection systems

  • Decrypt game code
  • Keys include:
    • Magic values loaded from tape (or disc)
    • Decryption code itself
    • Hardware timers & registers
    • Interrupt information

Accurate timing information

Visual 6502

ROL $fe48

Cycle Read / Write Address Description
0 Read 0d2d Read opcode (2e)
1 Read 0d2e Read low byte of address (48)
2 Read 0d2f Read high byte of address (fe)
3 Read fe48 Read memory at $fe48
4 Write fe48 Do rotate — writes unmodified value!
5 Write fe48 Store to $fe48

Fixing it


case 0x2e: // ROL abs
  addr = readword(pc); pc += 2;
  hardware.run(3);
  val = readbyte(addr);
  hardware.run(1);
  writebyte(addr, val); // unmodified value
  hardware.run(1);
  val = (val << 1) | (carry ? 1);
  carry = val & 0x100;
  writebyte(addr, val & 0xff); // modified value
  hardware.run(1);
  break;
                     

Cycle stretching

Performance

  • switch statements
  • Dynamic dispatch
  • Loop unrolling for video
  • Uint32Array for screen
  • WebGL
  • Deferred sound

Conclusion

Resources