## Submitting to the PowerShell + DevOps Global Su...
Created on: August 27, 2025
Answered using Deep Research by Chat01
Created on: August 27, 2025
Answered using Deep Research by Chat01
I thought of a high-level concept that I want to refine into a speaking proposal for the PowerShell + DevOps Global Summit 2026. I spoke in three sessions at the PowerShell + DevOps Global Summit 2025, so I know the general expectations and feel good about my chances of being selected.
The following is the call for proposals (CFP) for the 2026 PowerShell + DevOps Global Summit:
We are thrilled to invite you to submit your session proposals for the 2026 PowerShell + DevOps Global Summit, taking place in Bellevue, WA, from April 13-16, 2026. This Summit is the premier event for PowerShell and DevOps professionals, offering a unique opportunity to share knowledge, solve problems, socialize, and network with peers. Whether you're an Automater, Integrator, Problem-Solver, Tinkerer, Scripter, or Tech Wizard, this event is for you!
This year, we are looking for a diverse range of topics centered around PowerShell, DevOps, Cloud Computing, Automation, and other relevant subjects. While PowerShell has seen tremendous growth as a language, we are particularly interested in innovative uses of PowerShell, automation integrations, creative problem-solving approaches, and fresh applications of existing tools. The topics we are interested in include, but are not limited to:
If you're unsure whether your idea fits, ask yourself: "Will this make the PowerShell/DevOps community better?" If the answer is yes or even maybe, we want to hear from you.
We offer six types of sessions, each with associated speaker benefits. Please note that if there is more than one speaker, only the lead speaker is eligible for the honorarium and complimentary ticket:
Please ensure you have secured the necessary permissions before submitting your proposal.
We understand that some of you may rely on your company to cover travel expenses for this event. While we provide an honorarium, it may not cover all expenses. Therefore, if additional funding is required, please begin arranging these details during the submission and review period.
In addition to the honorarium, speakers will receive a complimentary conference pass. However, please note that only one speaker per session is eligible for these benefits. If you are co-presenting, benefits will only be extended to the primary speaker listed on the submission unless otherwise agreed upon in advance.
We will be using a two-round selection process:
This two-round selection process ensures a fair and thorough review of all submissions. The blind review in the first round eliminates bias, allowing us to focus solely on the quality and relevance of the content. This approach helps us select the best sessions based on merit before moving to a more detailed comparison in the second round.
We expect all speakers to review the travel and speaker benefit information outlined on the CFP page before submitting their proposals. Please ensure you are comfortable with the travel stipulations, especially if traveling internationally. There will be no additional compensation beyond what is clearly stated in the CFP.
In-Person Delivery: All sessions must be delivered in person. Remote or virtual presentations are not accommodated.
Language Requirement: Sessions must be delivered in English.
Thorough Review: Speakers are expected to thoroughly review all conference details, including speaker benefits and session requirements, prior to submission.
The Call for Proposals (CFP) will close on August 15th, 2025 at 11:59 PM. Please ensure you submit your proposal by this date, as no late submissions will be considered.
If you're ready to help shape the future of PowerShell and DevOps, we want to hear from you!
Submit your proposal now!
Five years ago, I wrote a chapter for the PowerShell Conference Book Volume 3 focused on data analysis with the backdrop of curating an arcade ROM collection for a Raspberry Pi-based arcade cabinet.
Here is the contents of the chapter that I wrote:
A> ## by Frank Lesniak
After buying a Pimoroni Picade, a miniature arcade cabinet meant to house a tiny computer known as a Raspberry Pi, I started researching arcade games and found the list to be both staggering and overwhelming.
Running retro-style arcade games on a modern computer means running arcade emulation software.
To do this on a Raspberry Pi, you must understand several versions of the emulation software, determine which of the thousands of games to run on the Picade (and on which versions of the emulation software), and finally, obtain the games themselves and load them onto the Raspberry Pi.
I did not intentionally set out to build an extract-transform-load (ETL) process or a "data warehouse," but doing so was a natural way to achieve my objective of figuring out which of the thousands of arcade games to run on the arcade system that I built.
Therefore, this chapter uses the backdrop of building an arcade system to explain the concepts behind using PowerShell for data processing.
In reading this chapter and following along with the suggested exercises, you can expect to:
Unless a software license, author, or publisher states differently, obtaining, using, or distributing commercial software products without paying for them is illegal, immoral, and unethical.
Accordingly, this chapter focuses on using arcade games that are understood to be free to use or possible for you to purchase.
Please do not commit software piracy by illegally downloading, using, or distributing commercial arcade games.
Since we use the backdrop of building an arcade system to explain the concepts behind PowerShell's data processing capabilities, it is vital to know a couple of key terms: emulation, ROMs, ROM packages, and machines.
Arcade cabinets hold electronics specific to a particular game, including one of many different types of microprocessors.
Older arcade cabinets had microprocessors quite different from those on today's modern computers, so you might be wondering how a modern computer can run the same software found within an arcade cabinet.
Luckily, modern computers can "pretend" to be the older hardware through a process known as emulation.
However, an emulator stops at the simulation of hardware; it does not include any software packages required to run games.
Arcade emulators use games stored in what are known as read-only memory ("ROM") packages.
Considering that these software packages include the game software itself plus some auxiliary information about the game's original arcade cabinet, the community also calls ROM packages "machines."
So, from this point forward, whenever you see ROM package or machine, understand the term to mean the software package required to run the game.
A> "To thy happy children of the future, those of the past send greetings."
A>
A> Inscription on the Alma Mater statue at the University of Illinois at Urbana-Champaign
With this chapter published and written at a point of time, please note that a lot can change in the world of arcade emulation as time advances.
While the author believes that the general principles conveyed in this chapter hold, the specifics of each emulator, relevant data sources, and URLs are subject to change.
With the principles conveyed in this chapter, you may find updated information on emulators and data sources, just know that you may need to use your favorite Internet search engine and do some searching.
At the most basic level, we need to determine a list of games to obtain and load onto the Raspberry Pi.
However, if you are of the same mindset as the author of this chapter, you may not want to pull a list from the Internet blindly; we may want to decide which games are on the list and which we exclude.
However, as you begin to research arcade games, it is clear that many factors influence the decision:
If it is not already clear, deciding on which ROM packages are "in" and which ones are "out" is complicated by the sheer number of considerations and the fact that we need to obtain and analyze data to get us to a decision.
It is best to start with the cleanest, most accurate data source available to perform our analysis.
Luckily, the arcade emulation software includes a database that has plenty of clean data to get us started.
At the time of writing, and as mentioned in the previous section, three arcade emulators work well on Raspberry Pi devices.
Also, each working ROM package pairs best with a particular emulator.
Therefore, it is highly likely that we need to use all three emulators on our Raspberry Pi arcade build, and so we must consider the database from all three.
The three emulators are:
If you are new to arcade emulation or not familiar with the differences in these three emulators, the author highly recommends pausing here and reviewing the page of background information bundled in the book's extras, in the document entitled ARCADE_EMULATOR_BACKGROUND_INFO.md
.
Reading this before continuing will allow you to better understand the analysis we perform later in the chapter.
Hopefully, you have taken a moment to read the page linked above, and you now understand MAME 2003 Plus, MAME 2010, and FBNeo and know the differences between them.
In that case, we are clear to retrieve our first database and begin our analysis.
For historical reasons, the community refers to emulator databases as "DAT files," so we use the term "DAT" moving forward to refer to these databases.
Luckily, all three development teams host each of their emulators on GitHub, and their DATs are there alongside the source code.
It might seem strange for these development teams to host their databases on GitHub, but remember that these DAT files are not transactional databases.
Updates are only necessary when the development team discovers new arcade ROM packages/machines, the developer's understanding of a ROM package changes, or the developers improve the emulation of a ROM package.
Conveniently, the databases are in XML format, which means we can access various object types and understand the relationships in the database, all by accessing a single file.
Through commit history or file-differencing tools, it is also straightforward to see what changed in the DAT as the developers release new versions.
To keep this chapter of reasonable length, we focus solely on one emulator.
Since MAME 2010 is not under active development at the time of writing, its DAT analysis is more likely to stay true over time.
And so, this chapter focuses on the analysis of MAME 2010's DAT.
The development team located it on the mame2010-libretro GitHub project site.
The DAT is in the metadata
folder, and the file name is mame2010.xml
.
Data engineers and data architects may cringe at the thought of using PowerShell in favor of some other language or approach, and to that, I say: "To each their own!"
PowerShell is the tool I use most-frequently for scripted data analysis because it is the one with which I am most familiar.
More importantly, it works on Windows, Linux, and macOS, it runs on most processors (I explain this in a moment), and it supports working with objects–unlike most other popular scripting languages.
I also picked PowerShell because PowerShell runs on Raspberry Pi, which you may recall is the tiny computer powering my arcade system.
Raspberry Pi is extremely popular in the retro gaming "scene," popularized by the software package called RetroPie.
A Raspberry Pi computer is quite different from a typical x86 desktop/laptop/tablet because a Raspberry Pi uses an ARM processor, which is an entirely different architecture from x86.
However, running PowerShell for data analysis on a Raspberry Pi is not for everyone.
First, if you are using a Raspberry Pi Zero (or Zero W), or if you are using the original Raspberry Pi (released in 2012), you cannot continue.
Unfortunately, .NET Core does not support the processor in a Raspberry Pi Zero/Zero W or the original Raspberry Pi, and PowerShell depends on .NET Core.
So, without .NET Core, we cannot run PowerShell!
It turns out that you need a Raspberry Pi 2 (or better) to have the right ARM processor for .NET Core (and thus, PowerShell).
Furthermore, I caution that data analysis in PowerShell requires much memory.
When one loads a large XML file such as the MAME 2010 DAT, PowerShell consumes 1 GB or more of RAM.
Accordingly, if you plan to perform the data analysis from your Raspberry Pi itself, I recommend a Raspberry Pi 4 (or better) with 4 GB of RAM or more.
If you do not have one of these models, don't despair; you may perform the analysis from your higher-performing desktop or laptop system (or a system hosted in a public cloud provider) instead.
We have already reviewed the URL of the MAME 2010 DAT.
We can retrieve the DAT file from PowerShell using Invoke-WebRequest
:
powershell$StrURL = 'https://github.com/libretro/mame2010-libretro/raw/master/' $StrURL += 'metadata/mame2010.xml' $StrContent = Invoke-WebRequest -Uri $StrURL
Now we have the XML file downloaded in its raw format and stored in memory as a string.
Having the data in a string is a good start, but string-parsing is not an effective way to process XML data.
Instead, let us cast to a native XML object using [xml]
:
powershell$XmlMAME2010 = [xml]$StrContent
Before we continue with analysis, we should view the first 140-or-so lines of the raw XML.
Well-structured XML has convenient DOCTYPE headers that provide us with an understanding of the data structures contained within the file.
To do this, we perform a string -split
operation on the raw (string) XML data using the newline character as the "splitter."
PowerShell represents the newline character as a grave accent mark–also known as a "backtick"–followed by a lowercase n.
However, note that PowerShell needs the newline character enclosed in double quotation marks (instead of single quotation marks) to process it correctly.
And if you are not familiar, a US keyboard places the grave accent mark as the key above Tab and next to 1.
<!-- pester on [Standard-CodeBlock] -->powershell$ArrContent = $StrContent -split "`n"
Then, we show the first 140 lines:
powershell$ArrContent | Select-Object -First 140
The output looks something like the following:
text<?xml version="1.0"?> <!DOCTYPE mame [ <!ELEMENT mame (game+)> <!ATTLIST mame build CDATA #IMPLIED> <!ATTLIST mame debug (yes|no) "no"> <!ATTLIST mame mameconfig CDATA #REQUIRED> <!ELEMENT game (description, year?, manufacturer, biosset*, rom*, disk*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*, softwarelist*)> <!ATTLIST game name CDATA #REQUIRED> <!ATTLIST game sourcefile CDATA #IMPLIED> <!ATTLIST game isbios (yes|no) "no"> <!ATTLIST game runnable (yes|no) "yes"> <!ATTLIST game cloneof CDATA #IMPLIED> <!ATTLIST game romof CDATA #IMPLIED> <!ATTLIST game sampleof CDATA #IMPLIED> <!ELEMENT description (#PCDATA)> <!ELEMENT year (#PCDATA)> <!ELEMENT manufacturer (#PCDATA)> <!ELEMENT biosset EMPTY> <!ATTLIST biosset name CDATA #REQUIRED> <!ATTLIST biosset description CDATA #REQUIRED> <!ATTLIST biosset default (yes|no) "no"> <!ELEMENT rom EMPTY> <!ATTLIST rom name CDATA #REQUIRED> <!ATTLIST rom bios CDATA #IMPLIED> <!ATTLIST rom size CDATA #REQUIRED> <!ATTLIST rom crc CDATA #IMPLIED> ...
From this output, we can infer two insights:
mame
element looks like it holds data about the MAME emulator itself.game
element subordinate to the mame
element looks more informative; after examining its attributes, it appears that it is the top-level object representing a ROM package.T> If you are working on the newest release of MAME (not MAME 2003 Plus or MAME 2010 but something much newer), note that the XML schema uses the identifier machine
instead of game
.
game
element includes a name
attribute that is required (we know MAME 2010 requires it because of the #REQUIRED
keyword).CDATA
, which tells us that it is a string.name
is unique within the database, and so we say that the name attribute is the primary key or index.isbios
, runnable
, cloneof
, romof
, and sampleof
AttributesReturning to the XML's DOCTYPE headers:
text... <!ELEMENT game (description, year?, manufacturer, biosset*, rom*, disk*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*, softwarelist*)> <!ATTLIST game name CDATA #REQUIRED> <!ATTLIST game sourcefile CDATA #IMPLIED> <!ATTLIST game isbios (yes|no) "no"> <!ATTLIST game runnable (yes|no) "yes"> ...
We can see that the game
's isbios
and runnable
attributes are string values, but each must equal yes
or no
.
Based on the default values supplied in the DOCTYPE headers, we also know that if the isbios
attribute is absent, we are to assume that its value is no
, and if the runnable
attribute is absent, we are to assume its value is yes
.
Therefore, we can get a list of standalone BIOS ROM packages using the following code:
powershell$ArrResults = @($XmlMAME2010.mame.game | Where-Object { ($null -ne $_.isbios) -and ($_.isbios -ne 'no') }) $ArrResults.Count
At the time of writing, we see that 51 ROM packages are standalone BIOS software (in other words: not a game).
We can examine a few examples using:
powershell$ArrResults[0] $ArrResults[25] $ArrResults[50]
Next, we can get a list of non-runnable ROM packages using the following code:
powershell$ArrResults = @($XmlMAME2010.mame.game | Where-Object { ($null -ne $_.runnable) -and ($_.runnable -ne 'yes') }) $ArrResults.Count
But notice that the count is zero!
That means that MAME 2010 does not include any ROM packages in its database marked as non-runnable.
Next are the cloneof
, romof
, and sampleof
attributes:
text... <!ELEMENT game (description, year?, manufacturer, biosset*, rom*, disk*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*, softwarelist*)> ... <!ATTLIST game cloneof CDATA #IMPLIED> <!ATTLIST game romof CDATA #IMPLIED> <!ATTLIST game sampleof CDATA #IMPLIED> ...
Because of the CDATA
type, we know these attributes are strings.
The #IMPLIED
flag tells us that these are optional attributes, so we can assume that if they are absent, the ROM package is not a clone, not a "ROM of" anything, and not using a "sample of" anything.
Unless you are an expert on MAME emulation, it is not immediately clear what any of this means–so let's find out!
Let us run a simple query to see our first example of the development team populating the cloneof
and romof
attributes:
powershell$ArrResults = @($XmlMAME2010.mame.game | Where-Object { (($null -ne $_.cloneof) -and ($_.cloneof -ne '')) -or (($null -ne $_.romof) -and ($_.romof -ne '')) }) $ArrResults[0]
We see the following:
textname : puckmana sourcefile : pacman.c cloneof : puckman romof : puckman isbios : no runnable : yes description : PuckMan (Japan set 2) year : 1980 manufacturer : Namco rom : {pacman.6e, pacman.6f, pacman.6h, prg7…} chip : {Z80, Namco} display : display sound : sound input : input dipswitch : {Rack Test (Cheat), Service Mode, Cabinet, Coinage…} configuration : configuration driver : driver
By examining the DAT entry for the ROM package puckmana
, we can see that its cloneof
attribute and romof
attribute are both populated and equal to puckman
.
Are these attributes always equal?
Let us check.
But before we do, let us first get a count of all ROM packages that have cloneof
or romof
populated:
powershell$ArrResults.Count
At the time of writing, we see that the total count of ROM packages with either cloneof
or romof
populated is 5112.
Let's see how many of these have cloneof
equal to romof
:
powershell$ArrResults = @($XmlMAME2010.mame.game | Where-Object { ( (($null -ne $_.cloneof) -and ($_.cloneof -ne '')) -or (($null -ne $_.romof) -and ($_.romof -ne '')) ) -and ($_.cloneof -eq $_.romof) }) $ArrResults.Count
At the time of writing, we have a count of 4310, which is less than the total of 5112 that we saw initially.
So, we can conclude that 802 (4310 subtracted from 5112) ROM packages do not have cloneof
equal to romof
.
We can confirm that our understanding is correct by running an inverse query:
powershell$ArrResults = @($XmlMAME2010.mame.game | Where-Object { ( (($null -ne $_.cloneof) -and ($_.cloneof -ne '')) -or (($null -ne $_.romof) -and ($_.romof -ne '')) ) -and ($_.cloneof -ne $_.romof) }) $ArrResults.Count
Sure enough, 802 games are on our list of ROM packages where the cloneof
attribute does not match the romof
attribute.
Let us examine a few random entries:
powershell$arrResults[0] $arrResults[200] $arrResults[400]
The last of these looks like:
textname : chocomk sourcefile : naomi.c romof : naomigd isbios : no runnable : yes description : Musapey's Choco Marker (Rev A) (GDL-0014A) year : 2002 manufacturer : Ecole Software biosset : {bios0, bios1, bios2, bios3…} rom : {epr-21576e.bin, epr-21576g.bin, epr-21576h.bin, epr-21576d.bin…} disk : disk chip : {SH-4, ARM7, AICA} display : display sound : sound input : input dipswitch : {Monitor, Unknown, Unknown, Unknown…} driver : driver
Each of the ROM packages that we just examined has romof
populated but not cloneof
.
So, we can hypothesize that when the DAT entry has romof
populated and romof
and cloneof
are not equal, then cloneof
is $null
(or absent).
Let us assess this theory:
powershell$ArrResults = @($XmlMAME2010.mame.game | Where-Object { (($null -eq $_.cloneof) -or ($_.cloneof -eq '')) -and ($_.cloneof -ne $_.romof) }) $ArrResults.Count
The count is the same, and so our testing upheld our hypothesis!
Incorporating the results of the author's added research, we can conclude:
cloneof
attribute and romof
attribute are both populated and equal to the cloned (parent) ROM package's name.
cloneof
attribute absent/blank, and the romof
attribute populated.romof
attribute would hold the name
of the BIOS ROM package for the standardized arcade platform (for example: the romof
attribute would contain nss
for Nintendo Super System).At this point, we have explored the data, developed a hypothesis, then assessed and upheld the hypothesis.
It turns out that the romof
attribute shows a ROM package dependency in the case of using what are known as merged ROM sets.
As we saw in our testing, the romof
attribute also can show a BIOS ROM package dependency for when the original arcade manufacturer based the hardware on a standardized arcade platform.
Both scenarios are relevant if using merged ROM sets because ROM packages configured in this manner do not include all required files in each ROM package.
However, we stated the earlier assumption that the reader is using non-merged ROM sets with integrated BIOS files.
Because of this assumption, we can ignore the romof
attribute as a decision criterion.
Similarly, we can ignore the sampleof
attribute as a decision criterion; if populated, it shows that a sound sample from the specified ROM package is needed.
The sound sample dependency would be relevant to building a ROM set, but it is not relevant to the immediate goal of determining which games to consider for the arcade cabinet.
Let us pause for a moment here.
In this section, we analyzed data that partially answers four of our decision criteria:
cloneof
attribute in the MAME DAT.isbios
attribute in the MAME DAT.runnable
attribute in the MAME DAT.Before we continue analyzing data in the MAME 2010 DAT, we should start thinking about how to capture our insights in some form of output.
Often, analyzing data is much easier if we first transform the data into a tabular format (that is: into a rows and cells format like that which one would see in Microsoft Excel).
All versions of PowerShell have built-in capabilities to read and write comma-separated values (CSV) files, so we use CSVs as a convenient tabular output data format.
When PowerShell reads a CSV file, each line of the CSV forms a PSCustomObject.
The PSCustomObject has a series of properties associated with it–each property's name is equal to the column header on the first row of the CSV file, and the property value is equal to the value of the column on that row of the spreadsheet.
To illustrate, take the following CSV:
text"Name","Title","Description" "Frank Lesniak","Senior Architect","PowerShell nerd" "Jen Lesniak","","Awesome for giving me time to write this chapter"
You can read this file into PowerShell with the following code:
powershell$ArrCSV = @(Import-Csv .\File.csv)
$ArrCSV
is now an array of two entries ($arrCSV.Count
is 2).
If we examine the first entry:
powershell$ArrCSV[0]
We see the following:
textName Title Description ---- ----- ----------- Frank Lesniak Senior Architect PowerShell nerd
Let us examine the object more-closely with Get-Member
:
powershell$ArrCSV[0] | Get-Member
We get more information about how PowerShell structures the object:
textTypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Description NoteProperty string Description=PowerShell Nerd Name NoteProperty string Name=Frank Lesniak Title NoteProperty string Title=Senior Architect
Notice the PSCustomObject
has three NoteProperties
.
If we set up our tabular data similarly, its export to CSV is a lot easier.
So, let us get to it:
<!-- pester off [Standard-CodeBlock] --><!-- pester on [Standard-CodeBlock] -->powershell$ArrCSVMAME2010 = @($XmlMAME2010.mame.game) | ForEach-Object { $Game = $_ $PSCustomObject = [PSCustomObject]@{ ROMName = $Game.name MAME2010_ROMName = $Game.name MAME2010_CloneOf = $( if ($null -eq $Game.cloneof) { '' } else { $Game.cloneof } ) MAME2010_IsBIOSROM = $( if (($null -eq $Game.isbios) -or ('no' -eq $Game.isbios)) { $False } else { $true } ) MAME2010_IsRunnable = $( if (($null -eq $Game.runnable) -or ('yes' -eq $Game.runnable)) { $true } else { $false } ) } $PSCustomObject }
For convenience, the code snippet above is in this book's Extras repository on GitHub.
For each game
(ROM package), we create a PSCustomObject
and then use Add-Member
to append NoteProperties
to it.
We can examine individual games by typing:
powershell$ArrCSVMAME2010[0] $ArrCSVMAME2010[1] # (etc.)
We can also output the constructed data to CSV by typing:
powershell$ArrCSVMAME2010 | Export-Csv '.\MAME2010DATInfo.csv' -NoTypeInformation
(though let's not write output yet–we still have plenty of work to do!)
description
, year
, and manufacturer
We can revisit the XML DOCTYPE headers by running the command:
powershell$ArrContent | Select-Object -First 140
When we do, we see the elements to review next are: description
, year
, and manufacturer
:
text... <!ELEMENT description (#PCDATA)> <!ELEMENT year (#PCDATA)> <!ELEMENT manufacturer (#PCDATA)> ...
All three have the designation (#PCDATA)
, which tells us that the three elements are strings and cannot have any further child elements.
From a PowerShell perspective, accessing these elements is the same as the other attributes we have accessed previously.
Let us look at a few examples:
powershell$ArrResults = @($XmlMAME2010.mame.game) | ForEach-Object { $_ } $ArrResults[500] $ArrResults[1000] $ArrResults[2000]
The latter of these looks like:
textname : bubblem sourcefile : taito_f3.c isbios : no runnable : yes description : Bubble Memories: The Story Of Bubble Bobble III (Ver 2.4O 1996/02/15) year : 1995 manufacturer : Taito Corporation Japan rom : {e21-21.20, e21-20.19, e21-19.18, e21-18.17…} chip : {68EC020, 68000, ES5505} display : display sound : sound input : input driver : driver
We can see that description
is more like the ROM package's "display name."
However, the other two attributes are what we expect–the year the arcade cabinet came into existence and the name of the company that manufactured the cabinet.
To incorporate this added information, we can add the following to the ForEach-Object
block of our data-transformation code:
<!-- pester on [Standard-CodeBlock] -->powershell# Add to ForEach-Object {} block # # Add DisplayName $DisplayNameParams = @{ MemberType = 'NoteProperty' Name = 'MAME2010_ROMDisplayName' Value = $( if ($null -eq $Game.description) { Write-Output ('') } else { Write-Output $Game.description } ) } $PSCustomObject | Add-Member @DisplayNameParams # # Add Manufacturer $ManufacturerParams = @{ MemberType = 'NoteProperty' Name = 'MAME2010_Manufacturer' Value = $( if ($null -eq $Game.manufacturer) { Write-Output ('') } else { Write-Output $Game.manufacturer } ) } $PSCustomObject | Add-Member @ManufacturerParams # # Add Year $YearParams = @{ MemberType = 'NoteProperty' Name = 'MAME2010_Year' Value = $( if ($null -eq $Game.year) { Write-Output ('') } else { Write-Output $Game.year } ) } $PSCustomObject | Add-Member @YearParams
For convenience, the code snippet above is in this book's Extras repository on GitHub.
If we incorporate and then run this code, we can examine our transformed, CSV-aligned output that we are building by viewing random entries:
powershell$arrCSVMAME2010[298] $arrCSVMAME2010[1997]
biosset
, rom
, disk
, and sample
Earlier, when we listed the MAME 2010 DAT's DOCTYPE headers, we saw that MAME 2010 includes subordinate elements that each, in turn, have attributes.
The first ones on the list are biosset
and rom
.
text... <!ELEMENT biosset EMPTY> <!ATTLIST biosset name CDATA #REQUIRED> <!ATTLIST biosset description CDATA #REQUIRED> <!ATTLIST biosset default (yes|no) "no"> <!ELEMENT rom EMPTY> <!ATTLIST rom name CDATA #REQUIRED> <!ATTLIST rom bios CDATA #IMPLIED> <!ATTLIST rom size CDATA #REQUIRED> <!ATTLIST rom crc CDATA #IMPLIED> <!ATTLIST rom md5 CDATA #IMPLIED> <!ATTLIST rom sha1 CDATA #IMPLIED> <!ATTLIST rom merge CDATA #IMPLIED> <!ATTLIST rom region CDATA #IMPLIED> <!ATTLIST rom offset CDATA #IMPLIED> <!ATTLIST rom status (baddump|nodump|good) "good"> <!ATTLIST rom optional (yes|no) "no"> ...
In MAME, these elements represent some of the data files that make up a ROM package.
A biosset
is a ROM package made up of low-level software associated with the emulated hardware.
If the MAME developers tagged a ROM package in the MAME DAT with biosset
information, then it shows that the ROM requires the contents of another BIOS ROM package to function.
However, as noted earlier, we assume the reader has built a non-merged ROM set, including BIOS files, so we do not need to worry about biosset
to meet our immediate goal.
From the raw XML, we see that subordinate rom
elements represent files that each have a name, SHA1/MD5/CRC hash, size, region information, and other metadata.
It turns out that an arcade ROM package is usually a ZIP-compressed file, a folder, or both, holding many smaller files, and each of the smaller files represents one of these rom
elements.
For our purposes, the most critical attribute is the rom
's status (baddump
/nodump
/good
) because it indicates whether the MAME 2010 development team knew of a complete, working copy of the software at the time of development.
Since these smaller rom
files make up most ROM packages, a completely functional ROM package requires that each non-optional
rom
file is of good
status.
In other words, one non-optional rom
file in the ROM package with a status of either baddump
or nodump
renders the entire ROM package non-functional.
So, think of a rom
file with a baddump
or nodump
status as a "knockout criteria" for our work.
The same approach applies to the disk
element:
text... <!ELEMENT disk EMPTY> <!ATTLIST disk name CDATA #REQUIRED> <!ATTLIST disk md5 CDATA #IMPLIED> <!ATTLIST disk sha1 CDATA #IMPLIED> <!ATTLIST disk merge CDATA #IMPLIED> <!ATTLIST disk region CDATA #IMPLIED> <!ATTLIST disk index CDATA #IMPLIED> <!ATTLIST disk status (baddump|nodump|good) "good"> <!ATTLIST disk optional (yes|no) "no"> ...
A disk
, more commonly called a CHD by the emulation community, represents software stored in the original arcade system on magnetic, optical, or flash media.
While a disk is typically larger than the individual rom
files, the same status
knockout criteria apply.
Therefore, for a given ROM package, if any of the rom
files or disk
files (CHDs) are not optional
and have a baddump
or nodump
status
, then we can assume the ROM software package as a whole is incomplete or non-functional.
The following code gives us a list of such incomplete or non-functional ROM packages:
powershell$ArrResults = @($XmlMAME2010.mame.game) | ForEach-Object { $Game = $_ $BoolCompletelyFunctionalROMPackage = $true @($Game.rom) | ForEach-Object { $File = $_ $BoolOptionalFile = $false if ($File.optional -eq 'yes') { $BoolOptionalFile = $true } if ($BoolOptionalFile -eq $false) { if (($File.status -eq 'baddump') -or ($File.status -eq 'nodump')) { $BoolCompletelyFunctionalROMPackage = $false } } } @($Game.disk) | ForEach-Object { $File = $_ $BoolOptionalFile = $false if ($File.optional -eq 'yes') { $BoolOptionalFile = $true } if ($BoolOptionalFile -eq $false) { if (($File.status -eq 'baddump') -or ($file.status -eq 'nodump')) { $BoolCompletelyFunctionalROMPackage = $false } } } if ($BoolCompletelyFunctionalROMPackage -eq $false) { $Game } }
For convenience, the code snippet above is in this book's Extras repository on GitHub.
After running this code, $ArrResults
is an array holding all the ROM packages that have a rom
file or CHD that has a status
of baddump
or nodump
.
At the time of writing, $ArrResults.Count
is 1204.
But wait–remember how the romof
attribute showed that a ROM package requires the files from a parent ROM package?
We need to consider those as well!
To illustrate, let us create a hashtable for easy ROM package lookups by name:
powershell$HashtableMAME2010 = @{} @($XmlMAME2010.mame.game) | ForEach-Object { $Game = $_ $HashtableMAME2010.Add($Game.name, $Game) }
Now, let us examine the ROM package 8bpm
:
powershell$HashtableMAME2010.Item('8bpm')
Note that it has a romof
dependency defined (in this example, 8bpm
is dependent on 8ballact
).
Next, we can examine 8bpm
's rom
files:
powershell$HashtableMAME2010.Item('8bpm').rom
The developers listed all files with a status of good
–with this narrow focus, we might mark the 8bpm
ROM package as fully working.
However, we did not consider its parent ROM:
powershell$HashtableMAME2010.Item('8ballact').rom
Two of the rom
files in the 8ballact
ROM package have a status other than good
, which means that both 8ballact
and its dependent ROM package 8bpm
are not functional ROM packages.
To address the need to check parent ROM packages, we use a recursive function to ensure that we not only check the immediate ROM package but also the parent ROM package(s).
The complete code for this solution is too large to review in the text of this book.
However, the author posted the full set of code to the Extras GitHub repository for this book in the script Convert-MAME2010DATToCSV.ps1
.
Before we move on, please note that the technique used above involved a hashtable for high-performance lookup operations.
When a database table has a primary key (such as the DAT file using the ROM package name
as a unique identifier for each ROM package), hashtables are a convenient way to use the primary key to index the table and allow an instant lookup.
We use this pattern in other scripts referenced later in this chapter to improve performance.
To round out this section, let us review the element sample
, which is the last element related to the files that make up the ROM package:
text... <!ELEMENT sample EMPTY> <!ATTLIST sample name CDATA #REQUIRED> ...
If present, the element sample
lists out the sound sample files that are part of this ROM package.
However, since we are assuming that the reader is already using a complete ROM set, we do not need to concern ourselves with sound samples.
display
, sound
, input
, dipswitch
, and driver
ElementsWhile continuing to share the details of the DAT file analysis is beyond the scope of what we cover in this chapter, this section describes at a high level the additional DAT elements to consider when analyzing data.
The script Convert-MAME2010DATToCSV.ps1
in the Extras GitHub repository for this book contains the actual code needed to perform the analysis and extract the full set of tabular data from the MAME 2010 DAT.
First, in the display
element, we can extract useful information such as the following:
The sound
element is straightforward.
We can simply note whether the ROM package has audio output based on the presence of the sound
element.
Next, analyzing the input
element is complicated, but worthwhile; it holds some of the most useful information, such as:
Analyzing the type of controls is complicated because we must first look-ahead to determine the schema of controls supported by all ROM packages in the MAME 2010 DAT.
The results of this look-ahead form the properties (columns) of our tabular data, so we need to have this complete understanding from the start.
However, the MAME development team changed the control schema in MAME version 0.149.
To be able to compare the MAME 2010 DAT to that of newer versions of MAME, we must translate the MAME 2010 control schema to an updated schema that is better-supported by the newest versions of MAME.
With this control metadata schema determined in advance, and with the schema translated to that of newer versions of MAME, we can then count the number of each type of control
that a given ROM package requires, and output the results in tabular format.
Next, we can use the dipswitch
element to answer a pair of questions:
Finally, we can tap into the driver
element to determine how well the emulator supports each ROM package, answering questions like:
good
, or imperfect
/preliminary
?Again the details of this analysis are in the script Convert-MAME2010DATToCSV.ps1
in the Extras GitHub repository for this book.
After we have tabularized the data and built upon the PSCustomObject data structure that we introduced previously, we can output the data to a CSV for later use:
powershell$ArrCSVMAME2010 | Export-Csv '.\MAME_2010_DAT.csv' -NoTypeInformation
Before continuing, let us see which decision criteria we have been able to answer just by using the emulator's DAT:
isbios
attribute) and if it has at least one display
element and at least one input
element.isdevice
attribute) and "mechanical" (ismechanical
attribute) ROM packages.cloneof
attribute tells us if an arcade manufacturer based the arcade system on another arcade system.cloneof
attribute for a given ROM package, the emulation community likely does not regard it as the best representation of the original arcade machine.
isbios
attribute answers this question for us.runnable
attribute and recursively examine each file in the ROM package's status
to confirm that the MAME developers knew of and tested a working copy of the arcade software at the time of development.driver
element to find what the MAME development team thought about the quality of the emulation of each ROM package.input
element to determine the number of buttons needed, and we can enumerate its subordinate control
element to determine the types of controls needed for each ROM package.control
other than a 4-way joystick (which is what Pimoroni included in the Picade), then we would know to exclude the ROM package.Not bad for only one data source!
We have not answered everything on our list.
To do so, we need to pull in more data sources and merge the data sets.
For brevity, instead of pulling in more data sets and merging the data in this text, let us instead review each open question and describe, at a high level, how to get the answer.
Q: At the time of writing, three different arcade emulators work well on a Raspberry Pi.
Do any of the emulators support this particular ROM package?
A: We would need to conduct a process similar to the one we just did for the MAME 2010 DAT, except conduct it for the MAME 2003 Plus DAT and the FBNeo DAT.
Afterward, we should have three CSVs–one for each emulator.
All three DATs (and CSVs) use the ROM package name
as the primary key or table index, so our next step would be to join the tables.
To perform a table join in PowerShell, I recommend using Join-Object.ps1, written by Warren Frame.
Download Join-Object.ps1, place it in your PowerShell working directory, then dot-source the file, like:
powershell. .\Join-Object.ps1
Note that the syntax for dot-sourcing is period space path-to-script
.
In this case, we are using a relative path on Windows, so the syntax for dot-sourcing is:
text<period> <space> <period> <backslash> Join-Object.ps1
Next, we need to load the CSVs into memory using syntax like the following:
powershell$CSVMAME2010 = Import-Csv .\MAME_2010_DAT.csv $CSVMAME2003Plus = Import-Csv .\MAME_2003_Plus_DAT.csv $CSVFBNeo = Import-Csv .\FBNeo_DAT.csv
Here, we have two options:
One way to join our tables is by performing an outer join on these tables as they exist.
This approach includes all the data and is best if the intention is to perform filtering later.
This approach is also the easiest, but PowerShell takes an extreme amount of time to complete the join operation.
If you take this approach, allow several hours for these commands to complete:
<!-- pester on [Standard-CodeBlock] -->powershell# First approach: Merge ALL data, slow $CSVInterimParams = @{ LeftObject = $CSVMAME2010 RightObject = $CSVMAME2003Plus On = "ROMName" JoinType = "Full" } $CSVInterimResult = Join-Object @CSVInterimParams $CSVAllResultsParams = @{ LeftObject = $CSVInterimResult RightObject = $CSVFBNeo On = "ROMName" JoinType = "Full" } $CSVAllResults = Join-Object @CSVAllResultsParams $StrExportPath = '.\MAME_2003_Plus_MAME_2010_and_FBNeo_Merged.csv' $CSVAllResults | Export-Csv -Path $StrExportPath -NoTypeInformation
The second way to join tables processes data more quickly by pre-filtering the results.
Although pre-filtering means fewer ROM packages in the output, we are filtering out ROM packages that are not useful to us.
So, it should not matter that we have fewer ROM packages in the output.
For example, you can apply a filter such as the following to the MAME 2010 data:
powershell# Second approach: Apply a pre-filter first $CSVMAME2010Filtered = $CSVMAME2010 | Where-Object { $_.MAME2010_CloneOf -eq '' -and $_.MAME2010_IsBIOSROM -eq 'False' -and $_.MAME2010_FunctionalROMPackage -eq 'True' -and $_.MAME2010_DisplayCount -eq '1' -and $_.MAME2010_ROMPackageHasInput -eq 'True' -and $_.MAME2010_P1_NumInputControls_dial -eq '0' -and $_.MAME2010_P1_NumInputControls_doublejoy_4way_4way -eq '0' -and $_.MAME2010_P1_NumInputControls_doublejoy_8way_8way -eq '0' -and $_.MAME2010_P1_NumInputControls_keyboard -eq '0' -and $_.MAME2010_P1_NumInputControls_lightgun -eq '0' -and $_.MAME2010_P1_NumInputControls_paddle -eq '0' -and $_.MAME2010_P1_NumInputControls_pedal -eq '0' -and $_.MAME2010_P1_NumInputControls_stick -eq '0' -and $_.MAME2010_P1_NumInputControls_trackball -eq '0' -and $_.MAME2010_OverallStatus -ne 'Preliminary' } | ForEach-Object { if ($_.MAME2010_NumberOfButtons -ne 'N/A') { if (([int]($_.MAME2010_NumberOfButtons)) -le 6) { $_ } } else { $_ } } | ForEach-Object { # Perform more filtering in an alternative way to avoid book line wrap $StrPropertyName = 'MAME2010_P1_NumInputControls_doublejoy_2wayhorizontal' $StrPropertyName += '_2wayhorizontal' $ArrProperty = @($_.PSObject.Properties | Where-Object { $_.Name -eq $StrPropertyName }) if ($ArrProperty.Count -ge 1) { if ($ArrProperty.Value -eq '0') { $_ } } } | ForEach-Object { # Perform more filtering in an alternative way to avoid book line wrap $StrPropertyName = 'MAME2010_P1_NumInputControls_doublejoy_2wayvertical' $StrPropertyName += '_2wayvertical' $ArrProperty = @($_.PSObject.Properties | Where-Object { $_.Name -eq $StrPropertyName }) if ($ArrProperty.Count -ge 1) { if ($ArrProperty.Value -eq '0') { $_ } } } # Then, apply a similar filter to MAME 2003 and FBNeo # Finally, run the filtered tables through the same Join-Object operation as # mentioned above, in the first approach
For convenience, the code snippet above is in this book's Extras repository on GitHub.
Q: Is the Raspberry Pi fast enough to run this ROM package?
A: At the time of writing, this question is difficult to answer.
On the RetroPie wiki page for MAME and FBNeo, there is a link to an All Arcade ROMS Compatibility List.
However, at the time of writing, the community has not updated it for the Raspberry Pi 4, and so it is hard to tell which games are suitable.
If the community updates the Compatibility List, then you can join it with other tables as outlined above.
Q: Does the game within the ROM package belong to a category that we enjoy playing?
and
Q: Does the ROM package have adult/sexual content that would be inappropriate for a young child to see?
A: The author is aware of five sources of this information:
Unfortunately, there is not a universally accepted definition of an arcade machine's category, so the schema of categories varies across these sources.
Additionally, these data sources are in varying formats, some of which are incredibly challenging to parse into a usable tabular format.
For example, the author of the "All Killer, No Filler" lists stored them as batch files intended to copy ROM packages.
Luckily, the author uploaded scripts to convert these files into a tabular format in the Extras GitHub repository for this book.
The relevant scripts in this case are:
ArcadeManagerClassicsListToCsv.ps1
Convert-ProgettoEmmaCatverIniToCsv.ps1
Convert-ProgettoSnapsCategoryIniFilesToCsv.ps1
Convert-ProgettoSnapsCatverIniToCsv.ps1
Create-ConsolidatedAllKillerNoFillerGameList.ps1
.Once you have obtained the data and used the scripts noted above to transform it, then you can join the tables with other tabular data using the same approach noted earlier.
Q: Is the ROM package in English, or at least playable by someone who only knows English?
A: Similar to the above, Progetto Snaps has a file called languages.ini that needs to be converted to CSV using the Convert-ProgettoSnapsLanguagesIniToCsv.ps1
script in the Extras GitHub repository for this book.
Once downloaded and converted to CSV, the reader can join the tables.
Q: Is the game any good?
A: Whether a game is "good" is highly subjective, but the community has built respect for at least three data sources:
The author's scripts (uploaded to the Extras GitHub repository for this book):
Convert-ArcadeManagerClassicsListToCsv.ps1
Convert-ProgettoSnapsBestGamesIniToCsv.ps1
Create-ConsolidatedAllKillerNoFillerGameList.ps1
Each can aid you in converting these three raw data sources into a tabular format.
Then, you can perform a join operation such as the one performed earlier to combine data sources.
The goals set at the beginning of this chapter were:
We covered these three objectives with the backdrop of deciding what games are applicable to someone building an arcade system.
Also, upon reflecting on the title of the chapter, recall that we extracted the MAME 2010 DAT file from a data source (GitHub).
We then transformed the data by converting a complex XML data structure to a tabular data set, and by deriving some insights along the way.
While we did not load the data into a traditional database, we easily could have; instead, we exported the data to CSV for later analysis.
And while we did not build a data warehouse in a traditional way, we took a more PowerShell-y approach and used a function to join several tables together in memory to extend our data model and achieve our objectives.
One closing thought for folks building their own arcade system and wanting to obtain ROM packages legally: very few arcade manufacturers have made their games available freely for non-commercial use.
The MAME development team's website provides one such list, along with download links.
However, at the time of writing, only 20 ROM packages are available free for non-commercial use!
Instead of building this complicated ETL process, it would have taken less time to look up each of these 20 games manually on the Arcade Italia Database and make our decisions manually.
Additionally, here is the supplemental material I wrote that explains the background required to appreciate the task:
If you are new to the world of arcade emulation, or not familiar with the differences between the emulators (or if you are asking yourself: what is an emulator?), it may be helpful for you to review the following background information before you dive into trying to create a ROM list.
Many arcade systems were created at a time when microprocessors and computer equipment were very different than today's computers.
As a result, we cannot merely take the arcade game software and run it on a modern microprocessor.
Instead, modern computer systems need to pretend or simulate that they are running the same microprocessor and hardware that the original arcade system had.
Emulation is the process of pretending or simulating a different hardware platform, such as those found in 1980s and 1990s arcade systems.
Once we can simulate an arcade system's original hardware, we still need the game's software.
The community calls the software required to run an arcade game a read-only memory (ROM) package, or sometimes just a ROM.
The term ROM package reflects the fact that the oldest arcade systems' software was permanently "etched" into read-only memory chips.
And because an arcade system typically had several of these memory chips, we call the entire package of software for one game a ROM package–that is to say that you have packaged up the ROMs, and they are ready to play.
At the time of writing, three arcade emulators work well on the Raspberry Pi 4.
Each working ROM package matches best with one of these three emulators, and so it is very likely that we need to use all three emulators on a Raspberry Pi arcade build.
Therefore, our analysis must consider all three.
The three emulators are:
MAME is an abbreviation for Multiple Arcade Machine Emulator.
It is still under active development, releasing a few versions per year, each adding support for new ROM packages or improving the support of existing ones.
Historically, the community at large called a milestone release in a given year "MAME YYYY," where "YYYY" is the release year.
For example, the community knows MAME version 0.78 as MAME 2003 because the development team released it in 2003.
The importance of this naming becomes clear in a moment.
The MAME team wrote the emulation software for modern, full-powered x86 computers and not for lower-performance ARM systems like the Raspberry Pi.
Luckily, some savvy developers "forked" point-in-time releases of MAME and modified them to work well on the Raspberry Pi.
Its development team started MAME 2003 Plus from a codebase fork based on MAME version 0.78, adding support for newer ROM packages over time (hence, the "Plus" designation).
They built support for the Raspberry Pi and continue to optimize it to run well.
Likewise, the community knows MAME 0.139 as MAME 2010, and a set of developers forked it to make it run well on Raspberry Pi.
However, unlike MAME 2003 Plus, MAME 2010 is not under active development.
Remembering that MAME adds support for new ROM packages over time, we can assume that MAME 2010 supports more ROM packages than MAME 2003 Plus.
However, with MAME 2003 Plus under active development, we can also assume that most ROM packages supported by both MAME 2003 Plus and MAME 2010 perform better in MAME 2003 Plus.
We know a ROM package is supported by both MAME 2003 Plus and MAME 2010 if the ROM package's name is present in both emulators' databases.
However, as the MAME development team releases new versions, they sometimes rename ROM packages or even remove them from the database.
A renamed ROM package can be challenging to identify across different versions of MAME and is beyond the scope of what we cover in this chapter.
However, an ambitious reader may use a "RenameSet" such as the one hosted by Progretto-Snaps to identify these renamed ROM packages programmatically.
In general, MAME is distinguished from other emulators by its wide variety of coverage of arcade systems, and its focus on emulation accuracy and historical preservation (e.g., the inclusion of non-playable "mechanical" arcade machines in its database).
If you happen to be reading this chapter and working with a version of MAME (or a fork) newer than version 0.162, then know that MAME also includes support for home console emulation through its merger with another emulator known as MESS.
However, the community generally recommends the use of individual console emulators (i.e., that focus on emulating one console very well) vs. using MAME for home console emulation.
FBNeo is short for FinalBurn Neo.
Its predecessor, FinalBurn, was the first emulator to emulate Capcom Play System (CPS) hardware, which made it popular with the emulation community.
The original developer moved on from there to add support for Neo Geo arcade systems.
So the community-at-large knows FinalBurn/FBNeo for its superior emulation of Capcom and Neo Geo systems compared to other emulator options.
Since the original FinalBurn emulator went open source, a new development team forked the codebase and continued development.
The team is still actively adding support for new ROM packages and improving the emulation of existing ones.
The emulator supports both modern, high-performance x86 systems and lower-powered ARM systems like the Raspberry Pi.
FBNeo and MAME overlap in their emulation support for arcade games, meaning that FBNeo, MAME 2003 Plus, and MAME 2010 may emulate a given arcade game.
Luckily for us, the FBNeo team aligned their database to match the ROM package-naming used in MAME's database.
So, if you take a ROM package supported by both FBNeo and MAME and compare the FBNeo database record to that from the most-current MAME release, the ROM package would be listed in both databases, and its name would be identical in each database.
You may be wondering which emulator to use when both FBNeo and MAME support a ROM package.
If the ROM package represents a Capcom or Neo Geo arcade system, FBNeo is almost always the correct choice.
However, if the ROM package does not represent a Capcom or Neo Geo arcade system, the answer is less clear and may depend on real-world testing.
Such testing is beyond the scope of this page, but you may find real-world test results by viewing the RetroPie MAME wiki page or FBNeo wiki page, and viewing the Compatibility List linked there.
Finally, note that if you happen to be working with the original FinalBurn or a previous fork known as FBAlpha, know that these versions also overlapped in emulation coverage with MAME.
However, the older emulators did not always align their ROM package-naming to that of MAME.
As you will see if you being to perform analysis on ROM packages, misaligned ROM package-naming makes it significantly more challenging to combine two data sets in a join operation.
Therefore, if you are working with Finalburn or FBAlpha instead of FBNeo, you need to use file hashes or otherwise create a ROM package "equivalency lookup table."
Retro gaming is a hobby of mine and I'm excited to share it with the community through a session in the format "Hands on Lab (4 Hours) - Extended, practical sessions where attendees can actively engage with the material. These interactive labs should include pre-prepared materials for participants to follow along." The session should focus on ad hoc and structured data analysis using PowerShell along the lines of the chapter I wrote in the PowerShell Conference Book. I want to stick with the arcade ROM topic.
Please review my initial thoughts. Based on my initial thoughts, please expand upon them. Then, generate a few session concepts that you think would be great for the PowerShell + DevOps Global Summit.
I'd like you to state the concept in prose format -- I am not asking you to write the CFP submission, yet. I'm simply asking for help generating ideas. Be as verbose as possible with the session concepts, as I intend to hand the information over to someone else.
Thanks for the detailed background and constraints—it’s clear you’ve done a lot of groundwork already. Before I help expand on your ideas and generate some robust session concepts, could you please clarify a few points:
These will help me fine-tune the session structure, title ideas, stretch goals, and how we present the lab’s value to both attendees and organizers.
Thanks! I’ll develop several fully fleshed-out session concepts for a 4-hour hands-on lab at the PowerShell + DevOps Global Summit 2026 based on your arcade ROM ETL idea. These concepts will highlight creative problem-solving, teach advanced PowerShell skills, and strike a balance between fun and transferability to the attendee’s day job.
I’ll include detailed session ideas with instructional structure, stretch goal options, and notes on how each lab could connect to real-world work problems. I’ll let you know once everything is ready for review.
Imagine a 4-hour Hands-On Lab where attendees use PowerShell to tackle a fun, non-traditional problem: curating an arcade game library for a Raspberry Pi-based retro arcade cabinet. This playful scenario serves as a vehicle to teach serious, transferable data engineering and automation skills. In the session, participants will extract data from various sources (like emulator databases and community game lists), transform it with PowerShell scripts, and load the results to answer a complex question – "Which arcade games should I include?" – all using real-world techniques applicable far beyond gaming.
Key elements of the lab:
Join-Object
script for merging data sets, or show how to use Import-Csv
/Export-Csv
for data exchange. These augmentations are optional but expose attendees to best-of-breed techniques in the PowerShell ecosystem.In summary, the expanded concept is a creative problem-solving deep dive. It leverages the novelty of arcade data to teach under-the-radar PowerShell techniques that many professionals haven’t seen in typical DevOps talks. It’s the kind of “Hey, nobody talks about this!” session that can both delight and educate. Below are a few different angles and titles for this lab that align with these ideas.
Concept: This version of the session highlights the journey from a nostalgic problem to real-world skills – essentially showing how a fun arcade challenge can make you a better PowerShell developer. The title “From Pac-Man to PowerShell” signals that we’re bridging two worlds. Attendees start with raw data about classic arcade games (e.g. lists of game ROMs, emulator metadata, community ratings) and end with a refined set of results, all through PowerShell scripting. We frame the lab as leveling up your data skills: each exercise is a new “level” in a game.
Invoke-WebRequest
or provided files to simulate pulling data from an API or repository. Next, we tackle transforming that data – for example, writing a PowerShell function to parse the MAME emulator DAT XML and filter out non-game entries. This is where we dive into parsing deeply nested XML, using techniques like XPath queries or navigating the object hierarchy that [xml]
casting provides. We proceed to aggregate and join with other data: one exercise will join the MAME data with another source (maybe a CSV of “Top 100 Arcade Classics” or a JSON file of game metadata). Attendees will use hashtables for high-speed lookups and a community Join-Object
function or manual looping to merge these sources, mimicking an ETL pipeline. Finally, in the “final boss level,” everyone produces a CSV (or even an in-memory SQLite database, for stretch goal folks) of the curated game list, and we discuss how they could “load” this into their Pi or any system – completing the ETL cycle.(This concept delivers a fun theme — leveling up through game-inspired stages — while covering serious PowerShell techniques in XML parsing, object manipulation, and multi-source data integration.)
Concept: This angle positions the session as a pure data engineering lab using PowerShell, but framed in the “Arcade” theme to keep it intriguing. The title “PowerShell Data Arcade” suggests a place where you come to play with data. The focus here is on the ETL (Extract, Transform, Load) aspect – treating the various arcade game data files as our mini data warehouse project. Attendees will build an ETL pipeline live, gaining experience with each stage in a PowerShell-centric way.
Invoke-RestMethod
or Invoke-WebRequest
to fetch the latest game list or download provided XML/INI/CSV files. We might have them extract data from an XML (emulator database), a CSV (community favorites list), and perhaps a web API (if available, or we simulate one). The instruction here covers using REST APIs with PowerShell and reading local files of different formats. We emphasize real-world parallels like pulling data from an internal company API or reading server inventories from CSV exports.isbios=$true
or runnable=$false
). Attendees will practice creating custom objects (PSCustomObject) to shape the data into a unified schema. For instance, they’ll create objects with properties like Name, Year, Manufacturer, EmulatorsSupported, Category, IsFamilyFriendly, etc., combining fields from all sources. This is where techniques like hashtable lookups come in (e.g. a hashtable keyed by ROM name to quickly find if a title is on the “classics” list). We also cover using conditional logic to derive new attributes (e.g. flagging a game as “Needs special controller” if our input data indicates it requires a trackball, demonstrating how to interpret metadata). By the end of this phase, each attendee has an in-memory data warehouse table (or a collection of objects) representing the curated arcade library.(Overall, this concept markets the session more directly as a data engineering lab for IT professionals, using the arcade project as the teaching medium. It’s a bit more straightforward in language, appealing to those who want to learn ETL in PowerShell and appreciate a unique example to do so.)
Concept: This idea puts front-and-center the notion that we’re doing analytics on an unusual data set (arcade games), yet extracting universal skills that any IT or DevOps professional can use. The title “Arcade Analytics: PowerShell Edition” suggests we’re treating the arcade data seriously, as one would corporate data – performing analysis and deriving insights – and the tagline of Unusual Data, Universal Skills drives home the transferable aspect. It’s pitched as a creative problem-solving session where out-of-the-box thinking with PowerShell yields results.
PSCustomObject
instances from scratch, populating them with data from different sources. For example, assembling a single object per game that contains properties coming from three or four input files (XML, JSON, INI, etc.). Attendees practice adding and removing properties on the fly, shaping objects to fit the analysis needs. This skill directly translates to creating custom output objects in scripts at work (for reporting or logging).ConvertFrom-Yaml
). We deliberately choose one data source that’s a bit gnarly – e.g. a deeply nested XML of game categories or a hierarchy of game clones. Attendees will learn to navigate these structures using a combination of techniques: the dot notation, Select-Xml
queries with XPath, and recursive functions. Mastering these means they can handle JSON responses from REST APIs or complex configuration files in their jobs with confidence.Join-Object
, the takeaway is that PowerShell can serve as a mini-ETL tool without needing SQL or a full database.Get-Content
or Import-Csv
to peek at raw data). Then, for each technical highlight listed above, we have a dedicated lab segment. For example, Segment A: Parsing nested XML (pull out all games that meet certain criteria from the emulator DAT file). Segment B: Build objects and add data from a JSON file of game reviews (demonstrating object manipulation and hashtable lookups for matching names). Segment C: Join with a CSV of parental ratings to filter out unwanted games (demonstrating join logic and further use of hashtables or PowerShell’s array features). Finally, Segment D: Summarize and output results – perhaps generate a simple text or HTML report listing the final chosen games and key stats (like how many were filtered out for each reason, which teaches basic grouping/aggregation in PowerShell).(In essence, this concept is pitched to attract those who want to sharpen their PowerShell problem-solving skills. It promises that by playing with “arcade analytics,” you’ll gain insights applicable to debugging scripts, analyzing logs, or any scenario requiring digging through data. It’s unique, practical, and memorable – exactly the kind of fresh content that can elevate the Summit’s agenda.)
Each of these session concepts delivers on the initial idea of a 4-hour, in-person lab where attendees learn advanced PowerShell techniques through the engaging lens of arcade game data. They differ slightly in focus and flavor:
All three remain hands-on, intermediate-to-advanced (300-level) in content, and align with the Summit’s call for innovative PowerShell use cases and deep dives. Any of these could be refined into a compelling CFP submission. The core promise is the same: attendees will walk out having built something cool and having learned techniques in PowerShell that few others are talking about, but that they can immediately apply in countless situations.