#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# usage: gen_romdb.py mupen64plus.ini
import io
import os
import re
import sys
from pprint import pprint # for debugging
from ConfigParser import ConfigParser
from collections import OrderedDict

OUTPUT_FILE='rom_luts.c'

if len(sys.argv) < 2:
    print("usage: %s mupen64plus.ini" % sys.argv[0])
    sys.exit(0)

gConf  = ConfigParser()
gGames = dict()

def get_save_type(t):
    return t.upper().replace(' ', '_') 

sys.stderr.write("Parsing " + sys.argv[1] + "...\n")
gConf.readfp(open(sys.argv[1]))
gNameRe = re.compile(r'([^(]+)', re.IGNORECASE)

gEeprom16k  = list()
gFlashRAM   = list()
gEeprom4k   = list()
gCountPerOp = list()

for section in gConf.sections():
    conf = dict(gConf.items(section))
    conf['crc'] = conf['crc'].replace(' ', '')
    conf['simplename'] = gNameRe.search(conf['goodname']).group(0).strip()
    name = conf['simplename'].lower()

    if not name in gGames:
        gGames[name] = []

    skip = False
    for game in gGames[name]:
        if game['crc'] == conf['crc']:
            skip = True
            break

    if not skip:
        gGames[name].append(conf)

# order by rom name
gGames = OrderedDict(sorted(gGames.items(), key=lambda t: t[0]))

# detect eeprom16k 
for _, games in gGames.items():
    for game in games:
        if game.get('savetype', '').lower() == 'eeprom 16kb':
            gEeprom16k.append(game)

        if game.get('savetype', '').lower() == 'eeprom 4kb':
            gEeprom4k.append(game)

        if game.get('savetype', '').lower() == 'flash ram':
            gFlashRAM.append(game)

        if 'countperop' in game:
            gCountPerOp.append(game)

print("Wrote " + OUTPUT_FILE)
romdb = open(OUTPUT_FILE, 'w')
romdb.write("/* This file was generated by gen_romdb.py */\n")
romdb.write("/* Games that use 16Kbit EEPROM */\n")
romdb.write("static const uint64_t lut_ee16k[] = {\n")

i = 0
for game in gEeprom16k:
    comma = ','

    if i == len(gEeprom16k) - 1:
        comma = ' '

    romdb.write('   0x' + game['crc'] + 'ULL' + comma + ' /* ' + game['goodname'] + " */\n")

    i = i + 1

romdb.write("};\n")

romdb.write("/* Games that use 4Kbit EEPROM */\n")
romdb.write("static const uint64_t lut_ee4k[] = {\n")

i = 0
for game in gEeprom4k:
    comma = ','

    if i == len(gEeprom4k) - 1:
        comma = ' '

    romdb.write('   0x' + game['crc'] + 'ULL' + comma + ' /* ' + game['goodname'] + " */\n")

    i = i + 1

romdb.write("};\n")

romdb.write("/* Games that use Flash RAM */\n")
romdb.write("static const uint64_t lut_flashram[] = {\n")

i = 0
for game in gFlashRAM:
    comma = ','

    if i == len(gFlashRAM) - 1:
        comma = ' '

    romdb.write('   0x' + game['crc'] + 'ULL' + comma + ' /* ' + game['goodname'] + " */\n")

    i = i + 1

romdb.write("};\n")

i = 0

romdb.write("/* Cycles per emulated instruction (aka CountPerOp) */\n")
romdb.write("static const uint64_t lut_cpop[][2] = {\n")
for game in gCountPerOp:
    comma = ','

    if i == len(gEeprom16k) - 1:
        comma = ' '

    if i == len(gEeprom4k) - 1:
        comma = ' '

    if i == len(gFlashRAM) - 1:
        comma = ' '

    romdb.write('   { 0x' + game['crc'] + 'ULL, ' + game['countperop'] + ' }' + comma + ' /* ' + game['goodname'] + " */\n")

romdb.write("};\n")
    
romdb.close()


