Git Product home page Git Product logo

romniscience's Introduction

Hmm. Tempted to throw all this out and start again. Just in case anyone was reading this.

ROMniscience

Lister for ROM images and associated header information, written in C# (targeting both .NET and Mono)

What does it do?

ROMniscience is a thing that gives you all the information secretly embedded in your ROM files and discs. A lot of game consoles use that information so they know how to execute that game correctly, display information to the user when starting up, or maybe just because the manufacturer of that console likes to have it there for their weird licensing/approval purposes. But hey, why question why the info's there? It is there, and it's mildly interesting. So why not? Also, if you have the datfiles from preservation communities such as No-Intro or Redump, it'll verify your files against those to tell you if they're correct or not.

In future, it'll give you the ability to browse filesystems contained inside that ROM, and have a few little tools to manage your ROM collection as well. But not yet.

But that's vaguely like this thing that already exists! Therefore this is a waste of time! Bah!

Well, first of all, I don't believe in this idea that you should not be allowed to make software that does similar things to another piece of software under the pretense that it's "wasteful". The phrase "reinventing the wheel" sucks. Maybe the only wheels available don't suit my needs exactly. Maybe I want to know how the process of making a wheel works. Maybe there's a monopoly on wheels and you can only buy them under certain conditions. Maybe I just want to make a wheel, y'know?

Anyway, I didn't know of a lot of these tools existed at the time. It's only after I got so far into development that it'd be too late that I was like "Oh! There's these things that also list ROM information". And I'm like "cool! How about that", and continued doing stuff. The thing is, disregarding that this is a hobby project for me and I like doing it anyway, I don't know what the aims of all those projects are and whether they have the same goals as me, or if they're even actively maintained, so I see it as still worth me doing this thing.

So what are those goals?

Ease of use / general UX stuff, clean-ish code (enough that it can be used as documentation for those kinds of people who want to read code as documentation, I guess), basically not doing stupid weird hacks, and accuracy: Be as sure that something is the correct way to read/parse/etc something as it is possible to be.

Sometimes I just make it up as I go along, but I force myself to stick to those three things.

What systems does it support?

At the time of writing:

  • APF-MP1000
  • Atari 8-bit computers
  • Atari 5200
  • Atari 7800 (but only the community-developed header)
  • ColecoVision
  • Commodore 64 (only some formats)
  • Dreamcast
  • e-Reader (slightly broken, see comments in that source file)
  • Game Boy Advance
  • Game Boy/Game Boy Color
  • GameCube
  • Konami Picno (experimental and based on guessing/observation rather than any info)
  • Neo Geo Pocket/Neo Geo Pocket Color
  • NES, FDS
  • Nintendo 64, 64DD
  • Nintendo DS
  • Nintendo 3DS
  • PC-FX
  • Pokemon Mini
  • PSP (only PBP files at this point)
  • RCA Studio II
  • Sega Master System/Game Gear
  • Sega Megadrive/Genesis, and by extension 32X, Mega CD/Sega CD and Sega Pico since they're the same format
  • Sega Saturn
  • SNES
  • Switch (homebrew only)
  • Uzebox
  • Vectrex
  • Virtual Boy
  • Wii, WiiWare, Wii homebrew folders for Homebrew Channel
  • WonderSwan (and therefore Benessee Pocket Challenge v2)
  • Xbox (.xbe only at this point)
  • Xbox 360 (.xex only at this point)

Anything else can still be listed to give you generic information, such as size, compression ratio, CRC32/MD5/SHA1, matches of those checksums against datfiles, and such. I've pretty much added every single system possible to get generic information like that. Yeah, every single system possible. All of them. You heard me. Every single one. Try me. I dare you. I have no life. I go out of my way to research obscure things for fun. You can't defeat me. I'm immortal.

You can also check in ROMniscience/Handlers, in case I forgot something on that list.

Will it support ?

Possibly! If you have documentation for a system that's only a stub handler, please do make me aware of it somehow, becuase then I'll probably be able to implement it. Some systems just kinda don't have documentation, though, because they're too obscure and nobody cares. Also, some systems don't have any kind of information to extract, which sucks. Also, it helps if I have dumps of that system, and sometimes I kinda don't. (I'd rather not unless I can find a way to dump real media myself, or there's homebrew which actually wants me to download it. You know what I mean? I'm a nice person and I don't like to pirate stuff.)

Howmst do I compile?

This uses the rather nifty library SharpCompress so you'll probably need that to build, though if I understand Visual Studio correctly, and I probably don't, you can right click the solution and do "Restore NuGet Packages" and it should all work. For end users, just make sure SharpCompress.dll is somewhere where I can see it, like in the same folder as ROMniscience.exe. That's why I put it there in each release.

Anyway, it'll build with Visual Studio 2017, and msbuild from Mono 5. Maybe with older C# compilers. Probably not. The version of xbuild present in Ubuntu 17.10's default respositories doesn't work, I know that much.

Can I help the project?

If you really want to... well, for developers, I haven't thought about a coding standards guide or stuff like that yet, so that'll happen later.

But if you're just scanning your ROMs and you see anything that says "Unknown"? Tell me about that value and what ROM it appears in and what's special about it. There may be mysterious secrets laying inside. Some value that corresponds to something that I didn't know about. That's one thing that comes to mind.

Hey! I get an exception with this compressed DVD file saying I'm out of memory.

Oh yeah. Should have mentioned, you can't really use .zip or .7z etc to compress really big files like DVD images. It's because I have to uncompress the whole file to memory, which is because of a limitation in SharpCompress where archive streams aren't seekable, and as I understand it that's because of a limitation in the algorithm used by those formats meaning they can never be seekable, no matter how clever of a programmer you may be. Which sucks, I guess. So the bottom line is that you can't really zip any super huge files. Yeah, I know, hard drive space isn't free.

Why's it called ROMniscience? That name sucks.

Well, because it's like omniscience, which is knowing all the things, and it's like ROM, and it knows all the things about your ROMs (in theory), so ROM + omniscience = ROMniscience and... look, naming stuff is hard, okay?

Why does [GUI thing] suck?

WinForms.

Why do you swear so much in your commit messages and comments?

I find it therapeutic.

Nobody is actually asking these questions! You're just padding out your readme whilst falsifying the impression that anyone actually asks questions about this.

Dang.

I have some other question that isn't covered here!

Well, ask away. I'm not an elitist, so if something confuses you and you'd prefer it not to, that's fine. It's just that I can't predict every single thing that people who aren't me don't know about this, because of course this is a thing I do know, because I made it, so I don't have a perspective of people who don't know it.

Unless it's like "what's a ROM?" or something, not because I think you're a terrible person for asking that, it's just that I don't know how to answer it.

So I guess that'll do for a readme? I should go to bed or something.

romniscience's People

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

fredatgithub

romniscience's Issues

More DS information

There's some things in here that's picked up by file(1) but not ROMniscience:

ARM9 offset being less than 0x4000 implies homebrew, since that's not actually supposed to happen
Secure area ID (first 8 bytes) being zeroed out implies multiboot
Secure area ID being 0xE7FFDEFFE7FFDEFF means decrypted (as the BIOS overwrites this once verified)
0x1000 being zeroed out apparently indicates the ROM is encrypted, however this should be noted: https://twitter.com/Myriachan/status/964580936561000448 (but perhaps we can do something with that anyway)

While I'm here and reading GBATEK, ARM9 offset >= 0x8000 implies no secure area, and maybe I could add that as an info item

Convert ROM formats

Alright, time to actually give myself issues for the things that I say I'm going to get around to doing one day.

For this one:

  • Convert .smd to .md (or whatever we want to call the Megadrive ROM extension for plain dumps)
  • Convert .v64 and .n64 to .z64
  • Remove copier headers from SNES ROMs
  • Anything else I forgot at this time, but those three are the most "important" I guess

Use the detected format instead of the filename extension, because extensions are often wrong with this sort of thing.

It should create a copy of the file, leave the original untouched. If it involves the original filename being wrong, like say we have to remove copier headers from something.sfc when something.sfc is actually a Super Wild Card file, normally we would output something.sfc but in order to avoid messing with anything output something.sfc.sfc or something (2).sfc instead (undecided, but the point is, avoid conflicts)

This would just go in a menu called "Manage" or something, and it would operate on multiple selected ROMs, and if any of them have errors it would collect all those errors for one error message box.
For the individual file view, have a button down the bottom perhaps.

Should also be accessible from the command line, speaking of, there's my next issue for myself...

Output invidiual ROM info to command line

Include a command line switch to input the information from the view individual file functionality to the command line instead of a dialog box. I'd want to make it a command line switch for that so that I don't break dragging and dropping a file onto the executable to show a GUI.

I guess one might also want to extract the images via command line too.

Add option to view DS banner title/icon even if version is invalid

The secret real reason I'm giving myself this issue is so I can force myself to revamp the settings system, because we'll need to do that. The issue itself is self-explanatory.

But I'm thinking we'll need to do something like this:

In Handler.cs, have a virtual property customSettings that returns IDictionary<string, SettingType> where the key is the name and value is an enum that represents the type of the setting, or perhaps if I can just use classes I'll do that.

So for DS it'll return {"display invalid banner versions", bool} or something like that.

Then for SettingsDialog.cs in FolderEditor (let's change the name of that class btw) we'll need to make new form elements appear underneath the folder text box according to the handler's customSettings property, which you pass in to the FolderEditor constructor. Append those to settingsToSave accordingly.

I guess as far as actually storing the values goes, you'd have things like DS_display invalid banner versions as the key. That just means you won't be able to use "enabled" as a custom setting without things getting screwy, but why would you?

Include Linux launcher

I can't drag stuff onto the .exe even though Mono exists, so that kinda bugs me, and I guess that's just Thunar's fault, but still.

It would also mean I could have ROMniscience available as an "open with" option and other integrationy things, I guess. Probably?

If it's a shell script I could also put it in /usr/local/bin.

It's just more convenient at the moment.

I'm tired.

Handle hash collisions

So, with the inclusion of CD stuff, we've noticed a problem.

It is in fact entirely possible that a given hash may in fact refer to two different things. Currently, ROMniscience just makes the assumption that the first hash it finds is correct.

Mainly seen with audio tracks, but it's possible that there are hash collisions anywhere else.

For example, 3B-C6-D1-19-C8-83-35-04-31-6E-B4-37-82-DC-1B-2B refers to not only an audio track on Pac-Man World: 20th Anniversary (USA), but also Pac-Man World: 20th Anniversary (France), and also something called Euro Demo 54.

The question is, what do we really do about that? It'll probably have a nasty performance hit to keep going through every datfile after a match is found to find more matches. As far as displaying it goes I guess the first match would show up in "Datfile game name / Datfile ROM name" / etc and have more columns "Datfile ROM name 2" and whatnot.

Cue sheets containing ISO files add the ISO twice

If it's like FILE "blah.iso" BINARY, it'll add that ISO twice, once normally and twice as referred to from the cue sheet.

It's not harmful, I guess, but might want to add a check to ROMScanner.processNormalFile to not add files that are already processed somehow.

Redo all the CD stuff

We don't need to view every single file in a cue sheet. Definitely not the audio tracks. Just refer to the relevant track, i.e. 1 in most cases, 2 for PC Engine CD, etc..

This will definitely make the UX design a lot easier...

Mono/Linux doesn't show images in the table

Well, right now it's because I skip over that code that would otherwise insert an image cell, but if I didn't do that, it would proceed to not display the image and screws up the cells to the right of where the image would be.

This is probably an upstream Mono bug but I'll leave it here for now until I get around to looking more into it.

Support text datfiles

Because I wanted to clean up the TODO comments and use those more for minor cleanups and whatnot, rather than major feature additions which I feel make more sense as issues.

This is a bit low priority I guess, since I'm not even sure what uses the old text-based format instead of XML, but they're floating around out there.

Read CD images

Add a generic way to handle disc images, abstracting the difference between .iso (2048 byte sectors) with .bin/.cue (with two files of course, and also 2352 bytes per sector because of 16 control bytes at the front which I don't think I need to read, and 288 error correction bytes at the end that I also don't think I need to read; although for datfile purposes I'll just read the whole thing first, it would only matter for any headers inside).

A good start would be Mega CD, since I already have the Megadrive handler and it'd be the same format, just with the need to take sector alignment into account with .bin/.cue as it ends up starting at 0x110 instead of 0x100.

Possibly add other formats like .chd if I can?

For DVD-based formats, there's no weird difference in sectors; as with GameCube/Wii discs. Presumably Dreamcast as well, though those just confuse me.

Allow multiple folders for one handler

Currently, ROMniscience only allows one folder for one handler. This is just because I store my ROMs like that (one system and one folder), and I figure most people do that too. But what if they don't? Especially when you have systems that you might want to group together, like Wii and WiiWare, which I don't put in the same folder but some people might, or maybe Megadrive and Mega CD once I get the latter working, or... whatever. I don't judge. And one of my software philosophies is that I don't judge the user on what weird shit they want to do.

Anyway, this shouldn't require too much thought on the backend, just as long as the settings file is backwards compatible (who knows, maybe someone who isn't me uses this program and I just don't know that yet). Configuring it in the GUI in a user-friendly way is the tricky part. As a last resort I guess we just have folders separated by | or ;, but that's ugly and makes the behaviour of the "choose folder" button non-obvious and confusing.

GCZ images don't identify in datfiles correctly

This is a weird one, because we can tell that the hashes are being calculated correctly, for example, Aquaman: Battle for Atlantis (USA) comes up with 55-2F-5D-D3-8C-E5-FE-18-9F-69-0B-E6-53-47-30-48 as expected. By formatting that properly (i.e. removing the dashes) and searching for it manually in the Gamecube datfile from Redump, it can be seen that this is indeed the correct checksum; however ROMniscience does not display it as being identified.

Disable rest of controls in settings dialog for disabled handlers

Sorry, me! You don't get out of touching that settings dialog forever. Not while I care about UX.

When a handler is disabled, the other items in that part of the dialog regarding that handler should also be disabled, e.g. the text box and calculate hashes checkbox; and of course should re-enable when you click the enabled button.

Have "view individual file" functionality accessible from main form

Have "Open" in file menu to just open stuff that way, but also "Open selected" to view the currently selected file (because the view individual file thing contains different information compared to the table)

I hope I can still understand what I just wrote when I come back to this one in the future because I can't right now

Autodetect file type (for individual file view)

Here's where it might get interesting.

For unknown file types, while we have let the user choose any handler to try and read it, maybe they don't know what it is.

Anyway, we'd have to add a thing to the Handler base class (providing a useless virtual method to make it optional for classes to override), and I guess it just takes a Stream or ROMFile and returns a bool, true if this could be handled by this handler (from looking at magic numbers, etc) or false if not.

Or perhaps it should return an enum with 4 possible values of it is a valid file, it might be a valid file, it probably isn't a valid file, and it definitely isn't? Or maybe that's too complicated.

PassMe DS ROMs are detected improperly

You could argue that it's because they are improper themselves, but anyway, according to file(1) where most cartridges would have the Nintendo logo, they instead have 0xC8604FE201708FE2; according to GBATEK that's just the ARM7 entry point in PassMe programs so it would be better to look for "DSBooter" at 0xa0 and "PASS" at 0xac; do that at the start of the DS handler because everything else is basically invalid

Let user force specific handler for individual file view

At the very least do this when you have an extension that isn't recognized by any other handlers, since right now it just does nothing in that scenario. If we can figure out an intuitive and user friendly way to do that when we already know what handler to use but the user wants to force another one for some reason, then yeah, do that as well I guess.

Use GTK# for Linux

I'm beginning to realise I really just gotta do this. It'll solve all the things. It'll probably solve #20. It'll make it usable on high-DPI screens.

Also by having multiple frontends by way of multiple build targets, we can probably have a CLI frontend too, which will solve #6 and #10. This should help with #9 as well.

Since the only reason we're hanging on to WinForms is portability, this also gives us the option to use WPF for Windows. That doesn't have to happen right away, as technically WinForms does work under normal Windows, but it becomes an option once we do the thing.

I'm not sure how this all works on Mac OS X, and I may have to enlist the help of someone else to ftest stuff, since I don't exactly have the hardware to run modern Mac OS X. Not sure if there's other platforms Mono runs on either. Until I can find out though, I'd better keep WinForms around.

Also I've just wanted to try GTK#.

Fix checksums

For systems where we're calculating the checksum for validation anyway, include an option to recalculate the checksum and put that back in the stored checksum in the ROM, so it's now valid if it wasn't before, etc.

I dunno, stuff. That should be enough info for me talking to myself via Github issues.

TSV export doesn't work properly on Linux

To be precise if there's stuff that contains \n, like DS banner titles, that will mess up the export when the platform newline character is just \n and not \r\n, because I don't quote the fields. I should quote the fields.

Rename ROMs according to datfiles

Likewise with the other ROM management ideas, this would be accessible from a menu and operate on several ROMs at once and be accessible from the command line, etc.

Anyway, this should take the datfile match if any, and rename the ROM to what it says, except with these options:

  • Don't change "The" to ", The"; I'll have to change it back
  • Don't rename anything starting with [BIOS] to the wrong extension, just leave that extension alone
  • Remove cruft like (SGB Enhanced) or (GB Compatible)
    It's already known how I feel about those, but maybe some people like them (I'm sure the No-Intro people do). Hence option.

Naturally avoid overwriting any existing file with the new name, but maybe it could be useful to at least inform the user after a batch rename if that ended up happening.

Generic tape/disk formats

So, we have generic CD handling. That's good. Yay!

Now that we've started adding weird computers and whatnot to the thing, we also have.. floppy disks. And tapes. And I mean like, MAME handles those generically, or something like that. Kinda makes sense, rather than implementing the same thing for every thingajiggy that uses a floppy disk or tape.

Well, I'm not feeling particularly good-at-wording, but you're me, so you'll understand what I'm on about. I hope.

Oh yeah, some formats are still specific to one system, e.g. .2mg still only makes sense for Apple IIgs, so keep that in mind I guess.

Perhaps we could also do .wav files for tapes and whatnot? Can System.Media.SoundPlayer be useful here?

Browse filesystem of selected ROM

Well, this would be accessible from the menu in the main window, but also the view individual file dialog of course.

This could be pretty useful, being able to see a full directory structure and also extract files from it (it'd pop up in a separate window with "Extract all" and "Extract selected" options). Also, to finish implementing the PSP handler so it can read UMD dumps, we'll need to implement ISO9660 more or less completely anyway.

Gamecube's filesystem would be a decent place to start since I've half-implemented it already to find the banner anyway, I can't remember if Wii uses the same thing or if it uses a slightly different filesystem implementation? And then DS, and ISO9660 (since PSP as mentioned uses that, and many CD based systems like Mega CD (IIRC) as well). Anyway yeah, stuff and things.

Revamp settings dialog

Bleh....

Alright me, I know you don't want to do this. But in the interests of UX, we must do this.

Other than switching to Qt or reimplementing an actually good layout manager in WinForms somehow or something, it's gonna have to be done.

So, here's my proposal.

Right now, we have what attempts to be a normal form layout for now. Name of the thing, file path text box, and browse button all in one line, squished in between one another.

This would work for anything that isn't WinForms. However, since you insist on using WinForms for cross-platforminess (which is kind of ironic the more I think about it), it won't work.

Here's what we'll do instead:

------ (yeah, one of those good ol' horizontal bars, or maybe something that just visually separates each thing)
Name of handler
File path text box + button
[x] Skip header when calculating hashes
[x] Some other option to do with this particular handler (for example, you could skip datfile identification for specific handlers if they take too long because they're so big and/or you're comfortable with your dumps being valid)
[Anything we want really! We can add all sorts of functionality to the settings dialog this way]
----

Much easier to implement and also scale correctly and whatnot, plus makes it easier to add new things.

It'll take more vertical space, yes, but we're using a lot of that anyway. Should be the most readable thing that we can have in this situation, I think.

Skip header when calculating checksums of NES roms

Hmm... maybe it could be an option.

My line of thinking is that the header sorta has to be there for the ROM to be useful (headerless ROMs are only much use if whatever's using them knows about the exact ROM already identified by checksum), so they sorta reasonably have to be there. No-Intro thinks they shouldn't be there though, just because they're a header.

Perhaps I could do this for Atari 7800 too. Maaaaybe SNES?

Refactor everything to use more classes more extensively

First of all, get rid of Tuple anywhere it's used, it's ugly and I hate it.

Secondly, Handler is fine and all, but instead of just adding to ROMInfo it should do something like add a BlahROM() which is a subclass of ROM(), or something like that. I'll figure it out as I go along, but the way it is now with this ROMInfo.info dictionary is definitely ugly.

Some GCZ compressed discs don't load banner correctly

Shrek Superslam (USA) and Wind Waker (PAL) load the icon fine, but throw an ArgumentOutOfRangeException trying to decode the banner text.

Some others aren't able to load the icon at all, and throw an IndexOutOfRangeException trying to do so:

Metal Gear Solid: The Twin Snakes (USA) (both discs)
Super Smash Bros Melee (PAL), also 20XX 4.05
Pokemon Colosseum (PAL)
Sonic Heroes (USA)
Mega Man X Collection (USA)
Star Fox Adventures (USA) rev 1
F-Zero GX (USA)
Beyond Good & Evil (USA)
Pokemon XD (PAL)
Baten Kaitos (USA) disc 2 (disc 1 is fine, which is very odd)
Eternal Darkness: Sanity's Requiem (USA)
Pokemon Colosseum Bonus Disc (Japan)
Pokemon Channel (Australia)

Let user force handler when choosing between ambiguous extensions

A continuation of #13 but I'm setting it aside for after 0.5.

This will probably require extending chooseChoices so I can add an additional button that gets placed on the generated form, and that button brings you to the list of all handlers to force.

Alternatively, a checkbox that toggles between showing handlers that handle the given file extension, or all handlers.

Either way I'm not getting out of modifying chooseChoices.

Wii homebrew handler

This is yet another issue I'm raising for myself where I had an idea about how to improve the code to be more flexible and extensible and this is a use case for such an idea.

So, if Wii homebrew games are going to be a thing... you're probably not going to get much out of just the .dol files. But they're all designed for the Homebrew Channel, so you have a meta.xml and an icon.png, which contain the things.

But how do we get at them, when the ROMFile passed to the handler only represents boot.dol? Well, because I like thinking too far ahead and planning the implementation before I even start on the concept, here's what I'm thinking:

Put a method in ROMFile: Stream getSiblingFile(string filename)
Returns a file with that name in the same folder as this file. Maybe validate against absolute paths or anything involving . or .. so we don't end up with any stupid security flaws (I'm not sure what the impact would be, given it'd be only called internally, but I just don't like the idea of blindly grabbing any relative path without making sure we're using things how we expect to be using them). Also, we're trying to get rid of InputStream and use StreamExtensions instead, so that cleanup might have to be done first.

But also if we're in an archive, get a file with the same name that's on the same level inside this archive. Remember that TODO comment where I wanted to refactor ROMFile so that it'd have a different class which is derived from some other base class for archived files and whatnot? That's probably a good idea to do first.

I'm not sure who archives their Wii homebrew folders since neither Homebrew Channel or Dolphin work that way, but it'd come in handy for other situations where we need another file that goes next to a given ROM.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.