private void installFunctionWithAnnotations(
      HLEFunction hleFunction, Method method, HLEModule hleModule) {
    HLEUnimplemented hleUnimplemented = method.getAnnotation(HLEUnimplemented.class);
    HLELogging hleLogging = method.getAnnotation(HLELogging.class);

    // Take the module default logging if no HLELogging has been
    // defined at the function level and if the function is not
    // unimplemented (which will produce it's own logging).
    if (hleLogging == null && hleUnimplemented == null) {
      HLELogging hleModuleLogging = method.getDeclaringClass().getAnnotation(HLELogging.class);
      if (hleModuleLogging != null) {
        // Take the module default logging
        hleLogging = hleModuleLogging;
      }
    }

    String moduleName = hleFunction.moduleName();
    String functionName = hleFunction.functionName();

    if (moduleName.length() == 0) {
      moduleName = hleModule.getName();
    }

    if (functionName.length() == 0) {
      functionName = method.getName();
    }

    HLEModuleFunction hleModuleFunction =
        new HLEModuleFunction(
            moduleName,
            functionName,
            hleModule,
            method,
            hleFunction.checkInsideInterrupt(),
            hleFunction.checkDispatchThreadEnabled());

    if (hleUnimplemented != null) {
      hleModuleFunction.setUnimplemented(true);
    }

    if (hleLogging != null) {
      hleModuleFunction.setLoggingLevel(hleLogging.level());
    }

    hleModule.installedHLEModuleFunctions.put(functionName, hleModuleFunction);

    addFunction(hleFunction.nid(), hleModuleFunction);
  }
  /**
   * Iterates over an object fields searching for HLEFunction annotations and if the specified
   * version is greater than the required version for that HLEFunction, it will install it.
   *
   * @param hleModule
   * @param version
   */
  public void installModuleWithAnnotations(HLEModule hleModule, int version) {
    if (installedModules.contains(hleModule)) {
      return;
    }

    try {
      for (Method method : hleModule.getClass().getMethods()) {
        HLEFunction hleFunction = method.getAnnotation(HLEFunction.class);
        if (hleFunction != null && version >= hleFunction.version()) {
          installFunctionWithAnnotations(hleFunction, method, hleModule);
        }
      }
      installedModules.add(hleModule);
    } catch (Exception e) {
      log.error("installModuleWithAnnotations", e);
    }
  }