set oc_map(0) brk_imp
unset oc_map

proc check_exist {opcode root} {
  global oc_map

  if {![catch {set foo $oc_map($opcode)}]} {
    puts "...!!!!! found $root on top of existing $foo"
  }
}

proc ins_std {root modes} {
  foreach p $modes {
    global oc_map
    set mode [lindex $p 0]
    set byte [expr [lindex $p 1]]
    set pair "[set root]_[set mode]"
    check_exist $byte $pair
    set oc_map($byte) $pair
    set verb "opcode_$pair"

    puts "@rmverb 6502:$verb"
    puts "@verb 6502:$verb tnt"
    puts "@program 6502:$verb tnt"
    puts "this:ea_[set mode]();"
    puts "this:core_[set root]();"
    puts "."
  }
}

proc ins_imp {ins byte} {
  global oc_map
  set byte [expr $byte]
  set pair "[set ins]_imp"
  set verb "opcode_$pair"
  check_exist $byte $pair
  set oc_map($byte) $pair
  
  puts "@copy 6502:$verb to 6502:__tmp"
  puts "@rmverb 6502:$verb"
  puts "@verb 6502:$verb tnt"
  puts "@copy 6502:__tmp to 6502:$verb"
  puts "@rmverb 6502:__tmp"
}

proc ins_imp_simple {ins byte mooexpr} {
  global oc_map
  set byte [expr $byte]
  set pair "[set ins]_imp"
  set verb "opcode_$pair"
  check_exist $byte $pair
  set oc_map($byte) $pair

  puts "@rmverb 6502:$verb tnt"
  puts "@verb 6502:$verb tnt"
  puts "@program 6502:$verb tnt"
  puts "$mooexpr"
  puts "."
}


proc ins_bra {ins byte mooexpr} {
  global oc_map
  set byte [expr $byte]
  set pair "[set ins]_rel"
  set verb "opcode_$pair"
  check_exist $byte $pair
  set oc_map($byte) $pair

  puts "@rmverb 6502:$verb"
  puts "@verb 6502:$verb tnt"
  puts "@program 6502:$verb tnt"
  # puts "this:ea_rel();"
  puts "this:core_branch($mooexpr);"
  puts "."
}


proc dump_opcodes {} {
  global oc_map

  puts "@rmverb 6502:init_opcodes"
  puts "@verb 6502:init_opcodes tnt"
  puts "@program 6502:init_opcodes tnt"
  puts {l = $list_utils:make(256, "invalid");}

  set keys [array names oc_map]
  set keys [lsort -integer $keys]
  
  foreach key $keys {
    puts "l\[$key + 1\] = \"$oc_map($key)\";"
  }

  puts "this.opcodes = l;"
  puts "."
}




ins_std adc "{imm 0x69} {zpg 0x65} {zpx 0x75} {abs 0x6D} {abx 0x7D} {aby 0x79} {idx 0x61} {idy 0x71}"
ins_std and "{imm 0x29} {zpg 0x25} {zpx 0x35} {abs 0x2D} {abx 0x3D} {aby 0x39} {idx 0x21} {idy 0x31}"
ins_std asl "{acc 0x0A} {zpg 0x06} {zpx 0x16} {abs 0x0E} {abx 0x1E}"

ins_bra bcc 0x90 {!this.p_c}
ins_bra bcs 0xB0 {this.p_c}
ins_bra beq 0xF0 {this.p_z}

ins_std bit "{zpg 0x24} {abs 0x2C}"

ins_bra bmi 0x30 {this.p_n}
ins_bra bne 0xD0 {!this.p_z}
ins_bra bpl 0x10 {!this.p_n}

ins_imp brk 0x00

ins_bra bvc 0x50 {!this.p_v}
ins_bra bvs 0x70 {this.p_v}

ins_imp_simple clc 0x18 {this.p_c = 0;}
ins_imp_simple cld 0xD8 {this.p_d = 0;}
ins_imp_simple cli 0x58 {this.p_i = 0;}
ins_imp_simple clv 0xB8 {this.p_v = 0;}

ins_std cmp "{imm 0xC9} {zpg 0xC5} {zpx 0xD5} {abs 0xCD} {abx 0xDD} {aby 0xD9} {idx 0xC1} {idy 0xD1}"
ins_std cpx "{imm 0xE0} {zpg 0xE4} {abs 0xEC}"
ins_std cpy "{imm 0xC0} {zpg 0xC4} {abs 0xCC}"

ins_std dec "{zpg 0xC6} {zpx 0xD6} {abs 0xCE} {abx 0xDE}"

ins_imp dex 0xCA
ins_imp dey 0x88

ins_std eor "{imm 0x49} {zpg 0x45} {zpx 0x55} {abs 0x40} {abx 0x5D} {aby 0x59} {idx 0x41} {idy 0x51}"
ins_std inc "{zpg 0xE6} {zpx 0xF6} {abs 0xEE} {abx 0xFE}"

ins_imp inx 0xE8
ins_imp iny 0xC8

ins_std jmp "{abs 0x4C} {ind 0x6C}"
ins_std jsr "{abs 0x20}"

ins_std lda "{imm 0xa9} {zpg 0xa5} {zpx 0xb5} {abs 0xad} {abx 0xbd} {aby 0xb9} {idx 0xa1} {idy 0xb1}"
ins_std ldx "{imm 0xA2} {zpg 0xA6} {zpy 0xB6} {abs 0xAE} {aby 0xBE}"
ins_std ldy "{imm 0xA0} {zpg 0xA4} {zpx 0xB4} {abs 0xAC} {abx 0xBC}"

ins_std lsr "{acc 0x4A} {zpg 0x46} {zpx 0x56} {abs 0x4E} {abx 0x5E}"

ins_imp_simple nop 0xEA {"@nop.com";}

ins_std ora "{imm 0x09} {zpg 0x05} {zpx 0x15} {abs 0x0D} {abx 0x1D} {aby 0x19} {idx 0x01} {idy 0x11}"

ins_imp_simple pha 0x48 {this:push_byte(this.a);}
ins_imp_simple php 0x08 {this:push_byte(this:status_byte());}

ins_imp_simple pla 0x68 {this.a = this:pull_byte(); this:status_nz(this.a);}
ins_imp_simple plp 0x28 {this:set_status_byte(this:pull_byte());}

ins_std rol "{acc 0x2A} {zpg 0x26} {zpx 0x36} {abs 0x2E} {abx 0x3E}"
ins_std ror "{acc 0x6A} {zpg 0x66} {zpx 0x76} {abs 0x6E} {abx 0x7E}"

ins_imp_simple rti 0x4D {this:set_status_byte(this:pull_byte()); this.pc = this:pull_word();}
ins_imp_simple rts 0x60 {this.pc = this:pull_word() + 1;}

ins_std sbc "{imm 0xE9} {zpg 0xE5} {zpx 0xF5} {abs 0xED} {abx 0xFD} {aby 0xF9} {idx 0xE1} {idy 0xF1}"

ins_imp_simple sec 0x38 {this.p_c = 1;}
ins_imp_simple sed 0xF8 {this.p_d = 1; player:tell("attempt to set decimal flag");}
ins_imp_simple sei 0x78 {this.p_i = 1;}

ins_std sta "{zpg 0x85} {zpx 0x95} {abs 0x8d} {abx 0x9D} {aby 0x99} {idx 0x81} {idy 0x91}"
ins_std stx "{zpg 0x86} {zpy 0x96} {abs 0x8E}"
ins_std sty "{zpg 0x84} {zpx 0x94} {abs 0x8C}"

ins_imp_simple tax 0xAA {this.x = this.a; this:status_nz(this.a);}
ins_imp_simple tay 0xA8 {this.y = this.a; this:status_nz(this.a);}
ins_imp_simple tsx 0xBA {this.x = this.sp; this:status_nz(this.sp);}

ins_imp_simple txa 0x8A {this.a = this.x; this:status_nz(this.a);}

ins_imp_simple txs 0x9A {this.sp = this.x;}

ins_imp_simple tya 0x98 {this.a = this.y; this:status_nz(this.a);}

dump_opcodes
