#!/usr/bin/wish
#/local/TclTk8.0/bin/wish8.0 -f
#/bin/sh -f
# the next line restarts using wish \
exec wish "$0" "$@"
# 
# Other, more specific ways of executing this program
# are to make the lines below the first line in the file,
# if you need to supply a specific path to wish.
#!/local/TclTk8.0/bin/wish8.0 -f
#!/usr/local/bin/wish

set SmallFont {Fixed 10 normal}
set Font {Fixed 12 bold}

if {[llength $argv] == 0} {
   puts "You need to supply a .s19 file as an argument!"
   puts "Usage: tksim11 somefile.s19  OR  tksim11 --help"
   exit
}
set progfile [lindex $argv 0]
if {"--help" == $progfile} {
   puts {Usage: tksim11 program.s19 [options]
  where program.s19 is a S19 file assembled from an HC11 .asm file
  and where a program.lst (ell-ess-tee) list file was also created.
  (Typically done by "as11 program.asm -l > program.lst".)

  Options include:
    -fontsize #  -- sets the font size (good #s are 10,12,14,18)
    -fontspec s  -- sets the complete font spec (experts only)
  }
  exit 0
}

if {[file extension $progfile] == ".s19"} {
   set listfile "[file rootname $progfile].lst"
} else {
   set listfile "$progfile.lst"
   set progfile "$progfile.s19"
}
if {![file readable $progfile]} {
   puts "I can't seem to find your file $progfile"
   exit
}
if {![file readable $listfile]} {
   puts "I can't seem to find your file $listfile"
   puts "tksim11 needs a listing file to use along with the .s19 file."
   puts "please generate one by doing 'as11 somefile.asm -l > somefile.lst'"
   exit
}
set simf [open "|sim6811_CUI $progfile" w+]
fconfigure $simf -blocking false
set docmd 0
set SimCmd ""
set AllDone 0

if {[llength $argv]>2} {
   set opt [lindex $argv 1]
   set optval [lindex $argv 2]
   if {"-fontsize" == $opt} {
      set SmallFont [list "Fixed" $optval "normal"]
   }
   if {"-fontspec" == $opt} {
      set SmallFont [split $optval]
   }
}

proc simwin {} {
   global SimCmd simf RegA RegB RegD RegX RegY RegSP RegPC RegCCR CycleCount
   # the IO side of the window
   frame .buttonfr -bd 2 -relief sunken
   frame .winfr -bd 2 -relief sunken
   frame .filefr -bd 1
   frame .iofr -bd 1 -relief sunken
   frame .simfr
   frame .regfr1
   frame .regfr2
   # -yscrollcommand ".simioy set" 
   text .simio -state disabled -width 55 -height 18 -font $::SmallFont
   # scrollbar .simioy -command ".simio yview"
   entry .rega -width 3 -textvariable RegA
   label .regal -text "A"
   entry .regb -width 3 -textvariable RegB
   label .regbl -text "B"
   entry .regd -width 5 -textvariable RegD
   label .regdl -text "D"
   entry .regx -width 5 -textvariable RegX
   label .regxl -text "X"
   entry .regy -width 5 -textvariable RegY
   label .regyl -text "Y"
   entry .regsp -width 5 -textvariable RegSP
   label .regspl -text "SP"
   entry .regpc -width 5 -textvariable RegPC
   label .regpcl -text "PC"
   entry .regccr -width 13 -textvariable RegCCR
   label .regccrl -text "CCR"
   entry .tcount -width 6 -textvariable CycleCount
   label .tcountl -text "Cycles"
   entry .tbreak -width 6 -textvariable BreakPoints
   label .tbreakl -text "BreakPoint"
   #entry .simin -width 50 -textvariable SimCmd
   #bind .simin <Return> DoSimCmd 
   button .simin -text "Exec 1 Instruction (step)" -command {DoSimCmd 1}
   button .simin10 -text "Exec 10 Instructions (step)" -command {DoSimCmd 10}
   button .simin100 -text "Exec 100 Instructions" -command {DoSimCmd 100}
   button .simin1k -text "Exec 1000 Instructions" -command {DoSimCmd 1000}
   button .simin10k -text "Exec 10000 Instructions" -command {DoSimCmd 10000}
   button .exit -text "Exit" -command DoExit
   pack .regal .rega .regbl .regb .regdl .regd .tcountl .tcount \
        .tbreakl .tbreak -in .regfr1 -side left -fill x
   pack .regxl .regx .regyl .regy .regspl .regsp .regpcl .regpc .regccrl \
        .regccr -in .regfr2 -side left -fill x
   # pack .simio .simioy -in .simfr -side left -fill y
   pack .simio -in .simfr -side left -fill y
   pack .regfr1 .regfr2 .simfr .simin .simin10 .simin100 .simin1k .simin10k \
        .exit -in .iofr -side top
   # The file editor side of the window
   text .filet -yscrollcommand ".filey set" -width 80  -height 35 \
        -font $::SmallFont
   scrollbar .filey -command ".filet yview"
   pack .filet -in .filefr -side left -fill both -expand 1
   pack .filey -in .filefr -side left -fill y
   # Button bar
   # button .exit -text "Exit" -command DoExit
   # button .use -text "Use File" -command "UseFile .filet"
   # button .save -text "Save File" -command "SaveFile .filet"
   # pack .exit .use .save -in .buttonfr -side left
   # packing all
   pack .iofr -in .winfr -side left -fill both 
   pack .filefr -in .winfr -side left -fill both -expand 1
   pack .winfr -side bottom -fill both -expand 1
   update
   after 1000
   #pack .buttonfr -side top 
}

proc DoSimCmd {Reps} {
   global SimCmd simf AllDone
   if {$AllDone} return
   .simio configure -state normal
   .simio insert end $SimCmd
   .simio configure -state disabled
   if {$Reps <15} {
      set step 1
   } else {
      puts $simf "s $Reps"
      set Reps 0
   }
   while {$Reps > 0} {
      puts $simf "$SimCmd"
      incr Reps -1
      if {$step} {
         flush $simf
         after 100 
         update
         if {$AllDone} return
      }
   }
   flush $simf
}

proc DoExit {} {
   global simf
   close $simf
   exit 0
}

proc UseFile {Textbox} {
   global SimCmd
   SaveFile $Textbox
   set SimCmd "use \"save.sim\";"
   DoSimCmd
}

proc SaveFile {Textbox} {
   set f [open save.sim w]
   puts $f [$Textbox get 1.0 end]
   close $f
}

proc readsim {} {
   global indata simf docmd AllDone BreakPoints
   global RegA RegB RegD RegX RegY RegSP RegPC RegCCR CycleCount
   set docmd 0
   after 50
   if {[eof $simf]} {
      DoExit
   }
   set havefirstline 0
   set indata [split [read $simf] "\n"]
   set li 1
   while {$havefirstline == 0} {
      set havefirstline [regexp {A ([0-9A-F][0-9A-F]) B ([0-9A-F][0-9A-F])    t=([0-9A-F]*)} [lindex $indata $li] dummy RegA RegB CycleCount ]
      incr li
   }
   regexp {D  ([0-9A-F][0-9A-F][0-9A-F][0-9A-F])} [lindex $indata $li] dummy RegD
   incr li
   regexp {X  ([0-9A-F][0-9A-F][0-9A-F][0-9A-F]) Y  ([0-9A-F][0-9A-F][0-9A-F][0-9A-F])[ 	]*breakpoints -> ([0-9a-f]*)} [lindex $indata $li] dummy RegX RegY BreakPoints
   incr li
   regexp {SP ([0-9A-F][0-9A-F][0-9A-F][0-9A-F]) PC ([0-9A-F][0-9A-F][0-9A-F][0-9A-F])} [lindex $indata $li] dummy RegSP RegPC 
   incr li
   #puts "$RegCCR"
   #puts "[lindex $indata $li]"
   regexp { *([0-9A-Fa-f][0-9A-Fa-f][^\)]*\))} [lindex $indata $li] dummy RegCCR
   incr li
   #puts "$RegCCR"
   # the lreplace gets rid of all the register lines, and blank lines and
   # the memory address header row. all that's left is memory rows, plus a
   # blank line at the end
   set indata [lreplace $indata 0 $li]
   .simio configure -state normal
   .simio delete 1.0 end
   foreach line $indata {
      # regsub -all {\.} $line {} line
      set line [format "%53.53s" $line]
      .simio insert end "$line\n"
   }
   .simio configure -state disabled
   # now hilite the listing file line (new: skip EQU and ORG lines)
   set linei 1
   while {1} {
      set linei [.filet search -nocase $RegPC $linei.0 end]
      if {"" == $linei} break
      regexp {([0-9]*)\..*} $linei dummy linei
      if {"" != [.filet search -nocase "equ" $linei.0 $linei.end]} {
         incr linei
         continue
      }
      if {"" != [.filet search -nocase "org" $linei.0 $linei.end]} {
         incr linei
         continue
      }
      break
   }
   if {"" != $linei} {
      regexp {([0-9]*)\..*} $linei dummy linei
      .filet tag delete curline
      .filet tag add curline $linei.0 $linei.end
      .filet tag configure curline -background yellow
      .filet see $linei.0
      set line [.filet get $linei.0 $linei.end]
      if {[regexp {end[ 	]*JMP[ 	]*end} $line]} {
         set AllDone 1
      }
   }
}

proc writesim {} {
   global indata simf docmd
   if {!$docmd} {
      return 
      #after 100
   }
   gets stdin cmd
   #puts "CMD: $cmd"
   puts $simf $cmd
   set docmd 0
   flush $simf
}

simwin

fileevent $simf readable readsim   
#fileevent $simf writable writesim

if {[file readable $listfile]} {
   set lf [open $listfile]
   .filet insert end [read $lf]
   close $lf
   set linei [.filet search -nocase -backwards jmp end]
   if {"" != $linei} {
      regexp {([0-9]*)\..*} $linei dummy linei
      set line [.filet get $linei.0 $linei.end]
      if {[regexp {^([0-9]*) ([0-9a-f]*) 7e} $line dummy lineno endaddress]} {
         puts $simf "b $endaddress"
         flush $simf
         after 10
      }
   }
}

while {1} {
  update
}
exit 0

#after 500
#while {![eof $f]} {
#    #while {[gets $f line] >= 0} {
#    #   puts "RAW: $line"
#    #}
#    set line [read $f]
#    puts -nonewline "RAW: $line"
#    gets stdin cmd
#    puts "CMD: $cmd"
#    puts $f $cmd
#    flush $f
#    after 250
#}