Pythonで書かれたSHマイコンのフラッシュライターに合わせて、DisktoolもPythonで開発しました。

また、Pythonのツールにより、このスクリプトは単一の実行ファイルに変換できますので、簡単に再配布可能といなっています。

import sys
from sys import exit
import os
from os.path import expanduser
import glob
import tkinter as tk
from tkinter import ttk
import tkinter.filedialog
from tkinter import filedialog

def loadfile(mot):
	listbox.delete(0, tk.END)
	motfile = path + '/' + combobox.get() + '/' + mot + '.mot'
	home = expanduser("~")
	fld = filedialog.askdirectory(initialdir = home)
	if len(fld) > 0:
		diskfile = fld + '.mot'
		files = os.listdir(fld)
		addr = readAddress(motfile)
		if addr == 0:
			status.set('Ignore system file')
			return
		writeSystem(diskfile, motfile)
		for f in files:
			fpath = os.path.join(fld, f)
			if os.path.isfile(fpath):
				listbox.insert(tkinter.END, f)
				addr = writeApp(diskfile, fpath, addr)
		s = 'S214' + format(addr, '06X')
		for i in range(16):
			s = s + "FF"
		fw = open(diskfile, 'a')
		fw.write(makeCheckSum(s) + '\n')
		fw.close()
		status.set(os.path.basename(diskfile) + ' is generated.')

def writeApp(diskfile, appfile, address):
	offset = address
	filename = os.path.basename(appfile)
	namesize = len(filename)
	filesize = os.path.getsize(appfile)
	s = 'S2{0:02X}{1:06X}'.format(namesize + 5, offset)
	for i in range(len(filename)):
		code = ord(filename[i])
		s = s + format(code, '02X')
	s1 = s + '00'
	offset = offset + len(filename) + 1
	s = 'S208{0:06X}'.format(offset)
	s = s + format(filesize % 0x100, '02X')
	s = s + format((filesize % 0x10000) // 0x100, '02X')
	s = s + format((filesize % 0x1000000) // 0x10000, '02X')
	s = s + format(filesize // 0x1000000, '02X')
	s2 = s;
	offset = offset + 4;

	fr = open(appfile, 'rb')
	fw = open(diskfile, 'a')
	fw.write(makeCheckSum(s1) + '\n')
	fw.write(makeCheckSum(s2) + '\n')
	count = 0
	while True:
		ch = fr.read(1)
		if len(ch) == 0:
			break
		if count > 15:
			s = 'S214' + s
			fw.write(makeCheckSum(s) + '\n')
			count = 0
		if count == 0:
			s = format(offset, '06X')
		code = ord(ch)
		s = s + format(code, '02X')
		offset = offset + 1
		count = count + 1
	s = 'S2' + format(count + 4, '02X') + s
	fw.write(makeCheckSum(s) + '\n')
	fw.close()
	fr.close()
	return offset

def makeCheckSum(srec):
	chksum = 0
	for i in range(2, len(srec), 2):
		code = int(srec[i : i + 2], 16)
		chksum = chksum + code
	chksum = ~chksum
	b = chksum % 256
	return srec + format(b, '02X')

def select_load():
	loadfile('mes2')

def select_core():
	loadfile('core')

def click_load(event):
	root.after(1, select_load)

def click_core(event):
	root.after(1, select_core)

def select_quit(event):
	exit()

def select_combo(event):
	inifile = path + '/disktool.ini'
	fw = open(inifile, 'w')
	fw.write('Select:' + combobox.get() + '\n')
	fw.close()

def writeSystem(diskfile, mesfile):
	with open(mesfile, mode='r') as fi, open(diskfile, mode='w') as fw:
		for line in fi:
			fw.write(line)

def readAddress(mesfile):
	data = '';
	s1 = ''
	s2 = ''
	s3 = ''
	count = 64;
	offset = 0;
	addr = 0;
	leng = 16;
	index = 0;
	with open(mesfile, mode='r') as f:
		for line in f:
			line = line.strip()
			if line[0:2] == 'S1':
				leng = int(line[2:4], 16) - 3
				addr = int(line[4:8], 16)
				s1 = line[8:8 + leng * 2]
			elif line[0:2] == 'S2':
				leng = int(line[2:4], 16) - 4
				addr = int(line[4:10], 16)
				s1 = line[10:10 + leng * 2]
			elif line[0:2] == 'S3':
				leng = int(line[2:4], 16) - 5
				addr = int(line[4:12], 16)
				s1 = line[12:12 + leng * 2]
			else:
				continue
			if offset != 0 and (offset + leng) != addr:
				break
			data = data + s1
			for i in range(leng - 3):
				s2 = data[index * 2 : index * 2 + 8]
				if s2 == '12345678':
					s3 = data[index * 2 - 6 : index * 2]
					return int(s3, 16)
				if s2 == '78563412':
					s3 = data[index * 2 - 4 : index * 2 - 2]
					s3 = s3 + data[index * 2 - 6 : index * 2 - 4]
					s3 = s3 + data[index * 2 - 8 : index * 2 - 6]
					return int(s3, 16)
				index = index + 1
			offset = addr
	return 0

path = os.path.dirname(sys.executable)
#path = '.'
files = os.listdir(path)
motlist = []
for f in files:
	motpath = os.path.join(path, f)
	if os.path.isdir(motpath):
		is_file1 = os.path.isfile(motpath + '/mes2.mot')
		is_file2 = os.path.isfile(motpath + '/core.mot')
		if is_file1 and is_file2:
			motlist.append(f)
if len(motlist) == 0:
	exit()
root = tk.Tk()
root.title('Disktool')
root.geometry('170x300')
canvas1 = tk.Canvas(root, height = 0)
canvas1.pack(fill = tk.X, side='top')
load = tk.Button(root, text='Load')
load.bind('<ButtonPress>', click_load)
load.pack(in_=canvas1, side='left')
core = tk.Button(root, text='Core')
core.bind('<ButtonPress>', click_core)
core.pack(in_=canvas1, side='left')
quit = tk.Button(root, text='Quit')
quit.bind('<ButtonPress>', select_quit)
quit.pack(in_=canvas1, side='left')
style = ttk.Style()
style.configure("office.TCombobox", padding=2)
v = tk.StringVar()
combobox = ttk.Combobox(root, textvariable=v, values=motlist, width=12, style="office.TCombobox")
combobox.bind('<<ComboboxSelected>>', select_combo)
combobox.pack(fill = tk.X, side = 'top')
combobox.set(motlist[0])
inifile = path + '/disktool.ini'
is_file = os.path.isfile(inifile)
if is_file:
	with open(inifile, mode='r') as f:
		for line in f:
			line = line.strip()
			lines = line.split(':')
			if lines[0] == 'Select':
				combobox.set(lines[1])
listbox =  tk.Listbox(root)
listbox.pack(expand = True, fill = tk.Y)
status = tk.StringVar()
status.set('')
label = tk.Label(root, textvariable=status)
label.pack(side='bottom')
root.mainloop()