#!/usr/bin/env ruby ############################################################################### ## http://www.6502.org/tutorials/6502opcodes.html ## This web page has information about each and every 6502 instruction ## Specifically: ## ## - Description of what each of the instructions do ## - Which modes are supported by which instructions, immediate, zero page ## zero page x, and y, absolute, indirect, relative etc. ## - The hex codes each instruction assembles to, in each mode. ## - The lengths in bytes of each instruction, by mode ## - The possibly variable number of cycles each instruction takes. ## ## There are 56 of them, and in my programmer laziness I just wrote this ## script to parse the page into the data structure that you see in ## opcodes.yaml. This really helped in creating the assembler, and ## it had basically everything I needed to know, and sped up writing ## this by huge factor. So, yay to this page, and this script! require 'yaml' ## Instruction name, and output structure to fill in. name = :adc output = {name => {}} ## Copy paste the tables from that website into this heredoc: text =<<-TEXT Immediate ADC #$44 $69 2 2 Zero Page ADC $44 $65 2 3 Zero Page,X ADC $44,X $75 2 4 Absolute ADC $4400 $6D 3 4 Absolute,X ADC $4400,X $7D 3 4+ Absolute,Y ADC $4400,Y $79 3 4+ Indirect,X ADC ($44,X) $61 2 6 Indirect,Y ADC ($44),Y $71 2 5+ TEXT ## And now iterate over each line to extract the info lines = text.split(/\n/) lines.each do |line| ## Grab out the values we care about parts = line.split cycles, len, hex = parts[-1], parts[-2], parts[-3] hex = "0x%X" % hex.gsub('$', '').to_i(16) match_data = cycles.match(/([0-9]+)(\+?)/) cycles = match_data[1] boundary = match_data[2] hash = {:hex => hex, :len => len, :cycles => cycles, :boundry_add => boundary != ""} ## And now decide which mode the line belongs to, collecting each listed mode hash = case line when /^Accumulator/ {:accumulator => hash} when /^Immediate/ {:immediate => hash} when /^Zero Page,X/ {:zero_page_x => hash} when /^Zero Page,Y/ {:zero_page_y => hash} when /^Zero Page/ {:zero_page => hash} when /^Absolute,X/ {:absolute_x => hash} when /^Absolute,Y/ {:absolute_y => hash} when /^Absolute/ {:absolute => hash} when /^Indirect,X/ {:indirect_x => hash} when /^Indirect,Y/ {:indirect_y => hash} when /^Indirect/ {:indirect => hash} when /^Implied/ {:implied => hash} else {} end output[name].merge!(hash) end ## Now output some yaml, and I only had to do this about 45 times ## instead of laboriously and mistak-pronely doing it by hand. puts YAML.dump(output).gsub("'", '') ## See opcodes.yaml