#!/usr/bin/env python

import argparse
import sys


def parse_args():
    parser = argparse.ArgumentParser(
        description='Convert IT modules to and from a plain-text format.')
    parser.add_argument(
        'infile', metavar='INFILE', help='input file (.it or .txt)')
    parser.add_argument(
        'outfile', metavar='OUTFILE', help='output file (.it or .txt)')
    parser.add_argument(
        '-v', '--verbose', action='store_true', help='enable verbose logging')
    return parser.parse_args()


def read_module(path, verbose):
    module = {}
    return module


def write_module(module, path, verbose):
    pass


def read_text(path, verbose):
    module = {}
    return module


def write_text(module, path, verbose):
    pass


def main():
    args = parse_args()

    if args.infile.lower().endswith('.it'):
        module = read_module(args.infile, args.verbose)
        write_text(module, args.outfile, args.verbose)
    elif args.outfile.lower().endswith('.txt'):
        module = read_text(args.infile, args.verbose)
        write_module(module, args.outfile, args.verbose)
    else:
        print('input file must have extension .it or .txt', file=sys.stderr)


if __name__ == '__main__':
    main()

@@ -20,34 +20,175 @@
 on%0A%0A
+from argparse 
 import 
-argparse%0Aimport sys
+ArgumentParser%0Afrom struct import unpack_from%0Afrom sys import stderr%0A%0A%0Aclass Namespace():%0A    def __str__(self):%0A        return str(self.__dict__)
 %0A%0A%0Ad
@@ -221,17 +221,8 @@
 r = 
-argparse.
 Argu
@@ -271,17 +271,16 @@
 T module
-s
  to and 
@@ -304,16 +304,125 @@
  format.
+ This '%0A                    'format includes only song name, orders, and pattern '%0A                    'data.
 ')%0A    p
@@ -615,144 +615,804 @@
     
-parser.add_argument(%0A        '-v', '--verbose', action='store_true', help='enable verbose logging')%0A    return parser.parse_args()%0A%0A%0Adef
+return parser.parse_args()%0A%0A%0Adef die(*args):%0A    print('fatal:', *args, file=stderr)%0A    exit(1)%0A%0A%0Adef read_module_pattern(data, offset):%0A    channels = %5B%5D%0A    # TODO%0A    return channels%0A%0A%0Adef read_module(path, verbose):%0A    with open(path, 'rb') as f:%0A        data = f.read()%0A%0A    if unpack_from('4s', data, 0x0)%5B0%5D.decode() != 'IMPM':%0A        die('%25s is not an IT module' %25 path)%0A%0A    mod = Namespace()%0A    mod.songname = %5C%0A        unpack_from('26s', data, 0x4)%5B0%5D.decode().strip('%5C0')%0A    ordnum, insnum, smpnum, patnum = unpack_from('4H', data, 0x20)%0A    mod.orders = unpack_from('%25dB' %25 ordnum, data, 0xc0)%5B:-1%5D%0A%0A    pattern_offsets = %5C%0A        unpack_from('=%25dL' %25 patnum, data, 0xc0 + ordnum + insnum*4 + smpnum*4)%0A    mod.patterns = %5B%5D%0A    for offset in pattern_offsets:%0A        pattern =
  rea
@@ -1423,40 +1423,68 @@
 dule
-(path, verbose):%0A    module = %7B%7D
+_pattern(data, offset)%0A        mod.patterns.append(pattern)%0A
 %0A   
@@ -1486,35 +1486,32 @@
 %0A%0A    return mod
-ule
 %0A%0A%0Adef write_mod
@@ -1513,27 +1513,24 @@
 e_module(mod
-ule
 , path, verb
@@ -1535,28 +1535,45 @@
 rbose):%0A    
-pass
+# TODO%0A    print(mod)
 %0A%0A%0Adef read_
@@ -1604,16 +1604,33 @@
  mod
-ule = %7B%7D
+ = Namespace()%0A    # TODO
 %0A   
@@ -1640,19 +1640,16 @@
 turn mod
-ule
 %0A%0A%0Adef w
@@ -1661,19 +1661,16 @@
 text(mod
-ule
 , path, 
@@ -1687,12 +1687,29 @@
     
-pass
+# TODO%0A    print(mod)
 %0A%0A%0Ad
@@ -1791,35 +1791,32 @@
 t'):%0A        mod
-ule
  = read_module(a
@@ -1859,27 +1859,24 @@
 ite_text(mod
-ule
 , args.outfi
@@ -1952,19 +1952,16 @@
      mod
-ule
  = read_
@@ -2016,19 +2016,16 @@
 dule(mod
-ule
 , args.o
@@ -2064,21 +2064,19 @@
         
-print
+die
 ('input 
@@ -2116,25 +2116,8 @@
 txt'
-, file=sys.stderr
 )%0A%0A%0A

Add some module-reading code to modtext.py