def parse_ref_words(argstr):
    # address: (expect, mask)
    """
    All three of thse are equivilent:
    ./solver.py --bytes 0x31,0xfe,0xff dmg-cpu/rom.txt
    ./solver.py --bytes 0x00:0x31,0x01:0xfe,0x02:0xff dmg-cpu/rom.txt
    ./solver.py --bytes 0x00:0x31:0xFF,0x01:0xfe:0xFF,0x02:0xff:0xFF dmg-cpu/rom.txt

    Which maps to:
    ref_words = {
        0x00: (0x31, 0xFF),
        0x01: (0xfe, 0xFF),
        0x02: (0xff, 0xFF),
        }
    """
    
    ret = {}
    auto_addr = 0
    for constraint in argstr.split(","):
        parts = constraint.split(":")
        assert len(parts) <= 3
        # One arg: assume offset and just use value
        if len(parts) == 1:
            offset = auto_addr
            value = int(parts[0], 0)
        # two arg: offset:value
        else:
            offset = int(parts[0], 0)
            value = int(parts[1], 0)
        mask = 0xFF
        # three arg: allow masking value
        if len(parts) >= 3:
            mask = int(parts[2], 0)
        ret[offset] = (value, mask)
        auto_addr += 1
    return ret