Samuel Pearce's Personal Website


Back to Main Page

6502 Virtual Machine made with WebAssembly

Click on the terminal window to enter input.
Press Escape to exit it again.

 


				
				
				
				

				

Disk Drive

Drop binary files here to load a program

Example Programs:

Here are some example programs I've written in 6502 assembly to run on this system. You can see the source code at the link provided below, or load them directly into the "disk drive" with the other button

Documentation & Explanation

This system is a simple emulation of a 6502 (65c02) computer running using WebAssembly. The memory map is as follows:

	+--------+ $0000-00FF	Zero-Page
	+--------+ $0100-01FF	Stack
	+--------+ $0200-FEFF	General Purpose RAM
	|        |
	|        |
	|        |
	|        |
	+--------+ $FF00-FFFF	I/O Page & Reset/Interrupt Vectors
	+--------+

The I/O Page includes following Addresses:

	$FF00	Console I/O
	$FF01	16-bit Disk address
	$FF03	Disk value
	$FF04	Disk Status

	$FF0F	Debug Address

	$FFFA	16-bit NMI Vector
	$FFFC	16-bit Reset Vector
	$FFFE	16-bit IRQ Vector

Console I/O works by reading from and writing to 0xFF00. Any bytes written to this address will be interpreted as ASCII and written to the terminal. Above 0x7F, there are some special characters that are interpreted as follows:

	0x80	Full block, Solid (█)
	0x81	Full block, Dark (▓)
	0x82	Full block, Medium (▒)
	0x83	Full block, Light (░)
	0x84	Half block top (▀)
	0x85	Half block bottom (▄)

	0xFF	Clear the console

If you read from the I/O port, it will either be a 7-bit ASCII character, or something with bit-7 set. If bit-7 is set, the keyboard isn't ready and hasn't received any input yet.

The debug address allows for simply debugging a program on the system. Any byte written here will be logged to the console, including what's stored at that address, and the state of all the system registers.

The disk drive is purely accessable through memory mapped I/O. The disk status byte indicates the following:

Status Flags:
	Bit 0:	Disk Available   Indicates a disk is in the drive if set
	Bit 2:	End of disk      Read/Write head is positioned at the end of the file
	Bits 3-7: Unused (for now)

The address is 16 bits (little-endian) meaning $FF01 is the low byte of the address and $FF02 is the high byte. If the address provided is outside the range of the disk (addr >= disk-size) it will always read 0x00, and any writes will extend the disk to include the new address, with any space in between filled with zeroes.

The bootloader ROM waits for a disk, reads two bytes (little-endian) for the starting address, then writes the following bytes to memory at the given location. Finally, it jumps to the given address to start executing the loaded code. This makes it compatible with C64-style PRG files.

A great benefit of being compatible with PRG files, is that there is an online assembler at www.masswerk.at that can export these kinds of files. So if you would like to give the VM a try, copy the assembly program below into the above listed assembler-website, assemble it, then generate and download the assembled binary in "Commodore PRG" format. Then, you can drag the downloaded file into the "Disk Drive", and it will load and run your program.

       .ORG $0200  ; Set program origin
                   ; to 0x0200
			
        LDX #$00   ; Init index to 0
 loop:  LDA helo,X ; Get next char
        BEQ end    ; End if char is '\0'
        STA $FF00  ; Write char to console
        INX        ; Increment index
        JMP loop   ; Repeat loop
			
  end:  JMP end    ; Loop infinitely
			
 helo: .ASCII "Hello, world!"
       .BYT $0A    ; Newline
       .BYT $00    ; Null-Terminator