All posts by Tidbytez

How to fix a noisy GPU fan

If you have an old GPU and you have noticed it is creating more noise now than when it was first installed, it may be because the bearing is no longer sufficiently lubricated.

A new fan off EBay, or new to you, might not be a sound investment. This is true assuming you can even find a replacement. Luckily most GPU fans can be serviced.

To Lubricate the Fan Bearing:

Remove the GPU from your computer.

Spin the fan manually. If it is not mostly silent, then there is a problem with the bearing. More than likely, there is just insufficient lubricant.

Carefully peel back the sticker on the top of the fan to expose the bearing. If access to the bearing is not provided on the top of the fan, then remove the fan from the GPU housing. Peel back the sticker on the back of the fan. If you see a yellowish mark on the inside of the sticker where the bearing is, this confirms the lubricant has leaked somewhat. If access to the bearing is not provided at the bottom of the fan either then very carefully try to remove the blade.

Once the bearing is exposed apply a small drop of light machine oil or sewing machine oil to the bearing. Singer oil is a good choice.

Rotate the fan manually to work the oil into the bearing.

Replace the sticker or use a small piece of tape to cover the bearing.

Before reinstalling the GPU, you might consider also applying fresh thermal paste to the GPU processor. This will help keep temperatures down, giving the fan less work to do.

How to fix no audio issues with RetroArch on Windows 10 or 11

To troubleshoot a sound issue with RetroArch, follow these steps:

  1. Check that DirectX 9 is installed on the PC. DirectX 9 is not part of Windows 11 by default and if you are running retroarch via an external drive, i.e. usb key, on a new machine it may not have the necessary runtime installed. It can be downloaded here: LINK Note: when the installer is run it will ask what folder to use. This folder is just a temp folder, essentially it is asking where the contents should be extracted. Once the process is finised navigate to the folder you chose and run the DXSETUP.exe file. Once this file has run you can delete the temp folder.
  2. Check if the RetroArch program is muted by pressing random keys on your computer. If it’s muted, go to Settings > Audio and turn off Mute.
  3. If the sound issue persists, try setting the default audio driver to Wasapi and unchecking WASAPI Exclusive Mode and WASAPI Float Format.
  4. If the volume mixer is the culprit, check if it’s listed on the volume mixer and check if RetroArch was set to low volume or muted. If it’s not listed, try downloading a new copy of RetroArch from their website and extracting it into a new directory.
  5. Restart after trying the solutions above.

Organizing ROM Files: How to Safely Move and Sort by Region

Typically there is a pattern to rom file names indicating what region the files belong to. For example it might explicitly state “(USA)” in the file name. However this alone cannot be taken as confirmation that “USA” means the game is from the USA region, USA could simply be part of the game title, e.g. “Daytona USA” etc. Japanese roms often end with the letter “j” but again this could just be part of the name of the game.

So how can one go about cleaning a rom folder without destroying these roms in the process?

You can still use these string elements to move files from one folder to another. The code below will not delete the files it will just move them en masse. If you have found a game was wrongly moved you can always return it.

Note: Always backup files and folders before you manipulate them programmatically.

The code below will need to be updated to reference your specific rom folder and where you want the files to move as well as the character string you are targeting i.e. *j.zip

@echo off

REM Examples file types:
REM Move Japanese files target is *j.zip
REM Move USA files target is *u.zip
REM Move USA files target is *(USA).zip
set target="*j.zip"

set source_folder="C:\roms\"
set destination_folder="C:\roms\_j_roms"

if not exist %destination_folder% (
    md %destination_folder%
)

move %source_folder%%target% %destination_folder%

echo Files with the extension %target% have been moved to %destination_folder%

How to Secure Your Azure SQL Database

  1. Authentication and Authorization:
    • Use Azure Active Directory (Azure AD) authentication for better security.
    • Implement firewall rules to control access to your database.
    • Assign minimal permissions to users based on their roles (principle of least privilege).
  2. Encryption:
    • Enable Transparent Data Encryption (TDE) to protect data at rest.
    • Use Always Encrypted to secure sensitive data in transit.
    • Consider client-side encryption for additional protection.
  3. Auditing and Monitoring:
    • Enable Azure SQL Auditing to track database activity.
    • Set up Azure Monitor to receive alerts and insights.
    • Regularly review logs and audit trails.
  4. Network Security:
    • Isolate your database using Virtual Network Service Endpoints.
    • Restrict public access and use private endpoints.
  5. Patch Management:
    • Keep your database engine up to date with the latest security patches.
    • Regularly review vulnerability assessments.
  6. Backup and Recovery:
    • Implement automated backups and test recovery procedures (remember a backup is only theoretically there unless it has been tested and proven to work).
    • Store backups conforming to the 3-2-1 Backup Rule explained below (do not assume your backups are safe just because they are in the cloud).

The 3-2-1 Backup Rule: Ensuring Data Resilience

The 3-2-1 Rule is a robust strategy that emphasizes redundancy, resilience, and data availability. Here’s what it entails:

  1. Three Copies of Your Data:
    • Maintain the original data and create at least two additional copies.
  2. Two Different Types of Media for Storage:
    • Store your data on distinct forms of media (e.g., hard drives, tapes) to enhance redundancy.
  3. At Least One Copy Off-Site:
    • Safeguard one backup copy in an off-site location, separate from your primary data and on-site backups.

By adhering to this rule, you mitigate single points of failure, protect against corruption, and ensure data safety even in unexpected events or disasters

How to get PICO-8 games to run on Retroid Pocket using Retroarch

One of the best ways to play PICO-8 games on a Retroid Pocket is via the Retroarch core retro8.

However you may run into the problem of only PICO-8 cart images being displayed rather than Retroarch launching the actual game.

You can solve this problem by doing the following:

Retroarch Settings > User Interface > File Browser > Use Built-In Image Viewer and set it on “No”. This way the image viewer will not get in the way, misinterpreting a PICO-8 cart as just a png file.

Happy Gaming!

How to add Android as a separate platform in Daijisho

Copy the text below and save it as Android.json

{
    "databaseVersion": 8,
    "platform": {
        "name": "Android",
        "uniqueId": "android",
        "shortname": "android",
        "description": null,
        "acceptedFilenameRegex": "^.*$",
        "scraperSourceList": [
            "RAW:Android"
        ],
        "boxArtAspectRatioId": 0,
        "useCustomBoxArtAspectRatio": false,
        "customBoxArtAspectRatio": null,
        "screenAspectRatioId": 0,
        "useCustomScreenAspectRatio": false,
        "customScreenAspectRatio": null,
        "retroAchievementsAlias": null,
        "extra": ""
    },
    "playerList": [
        {
            "name": "android - activity component player",
            "description": "Android activity component player",
            "acceptedFilenameRegex": "^$",
            "amStartArguments": "-n {android.activity}\n",
            "killPackageProcesses": false,
            "killPackageProcessesWarning": true,
            "extra": ""
        }
    ]
}

Open Daijishou > Settings > (Under All settings) Library > Import Platform > Select the Android.json file.

Now go to the Android Platform > Path > Sync

Note: It is not an official platform and you can flag whether an app is a game or not if you go to daijisho apps section and then long press on an app and mark it as a game/not a game. It will show up in this android platform after syncing. By default the emulators themselves will likely be wrongly flagged as games.

A generic python based ETL pipeline solution for Databricks

Below is the code necessary to create a Databricks notebook source file that can be imported into Databricks. This file can act as a template for creating ETL logic to build tables in Databricks. Once the notebook is prepared it can be set to run by a Databricks workflow job.

The template is parameterized. This means the developer just needs to provide the destination database, the destination schema, the destination table and the SQL logic.

(Note: this simple example is a full load solution and not a incremental load solution. An incremental load solution can be achieve by writing sufficiently robust SQL that is use case specific.)

The SQL is provided as a variable and the table or table names are stored in a list allowing for a large degree of flexibility for creating a single pipeline that builds multiple database objects.

Another important feature of the code is that it compensates for the fact that Databricks does not have a native acknowledgement of primary keys or restrictions on their violations. A list of primary keys can be provided and if any of those keys are null or not distinct the code will throw an error.

The code will also assign metadata fields to each record created including the job run id as the ETL id, the created date and the updated date.

# Databricks notebook source
# MAGIC %md
# MAGIC https://tidbytez.com/<br />
# MAGIC This is an ETL notebook.<br />

# COMMAND ----------

# Libraries
import os
from pyspark.sql import functions as F
from pyspark.sql.types import StringType
from pyspark.sql.functions import lit, concat_ws, isnan, when, count, col
from datetime import datetime, timedelta

# COMMAND ----------

# Functions

# Generate ETL ID
def get_etl_id():
    try:
        run_id = (
            dbutils.notebook.entry_point.getDbutils()
            .notebook()
            .getContext()
            .currentRunId()
            .toString()
        )
        if run_id.isdigit():
            etl_id = bigint(run_id)
            return etl_id
        else
            etl_id = bigint(1)
            return etl_id
    except:
        print("Could not return an etl_id number")


# Build database object
def build_object(dest_db_name, schema_name, table_name, pk_fields, sql_query):

    # Destination Database and table
    table_location = dest_db_name + "." + table_name
    # External table file location
    file_location = "/mnt/" + schema_name + "/" + table_name

    # Create Dataframe
    df = sql_query

    # Count nulls in Primary Key
    cnt_pk_nulls = df.select(
        [count(when(isnan(c) | col(c).isNull(), c)).alias(c) for c in pk_fields]
    ).collect()[0][0]
    # Dataframe record count
    cnt_rows = df.count()
    # Primary Key distinct count
    cnt_dist = df.dropDuplicates(pk_fields).count()
    # Error message
    message = ""

    # Join metadata to dataframe
    global meta_df
    meta = meta_df
    df = df.withColumn("key", lit(1))

    # inner join on two dataframes
    df = df.join(meta, df.key == meta.key, "inner").drop(df.key).drop(meta.key)

    # Write dataframe to table
    if cnt_pk_nulls == 0:
        if cnt_rows == cnt_dist:
            df.write.mode("overwrite").format("delta").option(
                "mergeSchema", "false"
            ).option("path", file_location).saveAsTable(table_location)
        else:
            message = "Primary Key is not unique"
    else:
        message = "Primary Key contains nulls"

    if message != "":
        raise Exception(message)


# COMMAND ----------

# Variables

# Destinations

# File location
schema_name = "YOUR_SCHEMA_NAME_HERE"

# Database location
dest_db_name = "YOUR_DEST_DATABASE_NAME_HERE"

# PK fields
pk_fields = ["EXAMPLE_ID", "EXAMPLE_LOCATION"]

# Metadata
etl_id = get_etl_id()
t = datetime.utcnow()

# Create metadata dataFrame
data = [(1, etl_id, t, t)]
columns = ["key", "ETL_ID", "CREATED_DATE", "UPDATED_DATE"]
meta_df = spark.createDataFrame(data, columns)
meta_df = meta_df.withColumn("ETL_ID", meta_df["ETL_ID"].cast("int"))

# COMMAND ----------

# Table name variable list
table_list = [
    {"table_name": "EXAMPLE_TABLE"}
]

# COMMAND ----------

# Iterate through table variables
for i in range(len(table_list)):

    table_name = table_list[i].get("table_name")

    # SQL query
    sql_query = spark.sql(
        f"""
        SELECT 1 AS EXAMPLE_ID,
        'TEXAS' AS "EXAMPLE_LOCATION"
        """
    )
    build_object(dest_db_name, schema_name, table_name, pk_fields, sql_query)

How to fix Dolphin GameCube controller button mappings and keep them from being overwritten by RetroBat or Emulation Station

RetroBat and Emulation Station do a great job of mapping controller buttons straight out of the box but sometimes these settings do not map correctly onto specific emulators.

Dolphin’s GameCube is one such emulator that seems to get the buttons jumbled.

If you have ever tried to fix the button mappings via Dolphin directly you might have been frustrated that your manual settings have not stuck as next time you run a game you are back to the same wrong button layout.

This is because RetroBat or Emulation Stations front-end settings take precedence over the individual emulator settings, i.e. the expectation is you will set the emulator settings via these front-ends not in the emulators individually. Mostly this works great however some of the more detailed settings cannot be set via the front-ends and the front-ends overwrite the emulators with incorrect default settings.

To solve the GameCube button mapping problem do the following:

Open Dolphin directly, there are various means to achieve this one being via the RetroBat settings.

Click on the Controller icon.

For each port (controller you have connected) click on the “Configure” icon.

In the “Device” drop down select your controller.

In the GameCube Controller options set the buttons as follows:

For a PlayStation controller:

A : Cross

B : Square

X : Circle

Y : Triangle

Z : R1

Start: Start (Options)

For a XBox controller:

A : A

B : X

X : B

Y : Y

Z : Right Bumper

Start: Start

Now save the settings as a profile.

Reopen RetroBat/Emulation Station and press Start on your controller.

From the Main Menu:

Game Settings > Per System Advanced Configuration > GameCube > Autoconfigure Controllers = “OFF”

This should resolve the problem going forward.

Fire Toolbox Vs the Amazon HD 8 Tablet (2022)

Amazon’s Fire tablets may not provide a complete Android experience, but they can still satisfy most user’s basic needs. They are priced very affordably, but this comes at the cost of locked bootloaders, no Google Play certification, and a heavily customized skin (Amazon’s Fire OS) that is often based on older Android versions and is, let’s face it, horrible to use. However, the aftermarket development community has managed to overcome most of these limitations with the Fire Toolbox.

See link below:

https://www.xda-developers.com/amazon-fire-toolbox-helps-install-google-apps-change-launchers-and-more-on-amazon-fire-tablets/

However the typical means of de-amazonification is not fully functional on the HD 8 Tablet.

Some important features still work like:

Remove lock screen ads

Block OTA updates

Debloating Apps

However setting a third-party launcher app as the default launcher has become buggy. The most popular choice, Apex, will likely not work. The launcher Lawnchair seems to work without and problems though. It’s a very basic launcher but totally serviceable.

Most importantly thought, as of now July 2023, the feature to install the Google Play store and Google Services does not work.

This means apps like YouTube, even if you side load them, will not work. Perhaps a suitable workaround for this, if you are concerned about your data privacy, is to install Firefox open YouTube as a webpage and then go to settings and choose “Install”. This will create a shortcut on your Home Screen that looks and functions like an app.

To install apps without the Play store you can install alternatives like the F-Droid store, Aurora store (only use a disposable Gmail account) or use APKMirrror. (Use all suggested alternatives at your own risk)

All of the above is less than ideal though so if you were thinking about picking up a cheap Fire Tablet on Prime day with the expectation it can be totally de-amazoned with a few clicks of a mouse, maybe give it a miss and pay a few extra bucks for something else instead.

How to replace multiple words within a string at once using python

Below is a quick code snippet example you can reuse to replace multiple words within a string using python.

s = "The quick brown fox jumps over the lazy dog"
print(s)
for r in (("brown", "red"), ("lazy", "quick")):
    s = s.replace(*r)
print(s)