-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SMS cart region detection #17
Comments
I thought about this for a bit. It's definitely possible, but not all commercially released games followed this guideline: https://www.smspower.org/Development/ROMHeader#RegionCode0x7fff05Bytes However, because there is no "PAL" region code, the benefit is almost totally eradicated if you attempt to detect from the region header within the core. Therefore, the only feasible way I can think of would be to use a DB in Main, which is undesirable from a portability standpoint and the principle of keeping complexity of Main to a minimum. A simple python script could be devised to create a DB of the header information and identify all the header characteristics of every SMS game dumped, however there will be a lot of false positives as companies didn't always follow this guideline. So more of a manual DB using hash checks would have to be created instead, which thankfully the library isn't that large so I could write one up pretty quickly, or maybe a software emulator already has this. Detecting quirks in Main via a DB lookup is preferable from the perspective of keeping the register count in the core down though, like N64. EDIT: ekeeke, as usual, has a thorough DB for the various mappers available here in c, so you could understand better the possible benefits: https://github.com/ekeeke/Genesis-Plus-GX/blob/master/core/cart_hw/sms_cart.c PAL specific timings --> https://github.com/ekeeke/Genesis-Plus-GX/blob/master/core/cart_hw/sms_cart.c#L223-L242 |
It's not worth to make such DB because there will be always some mods which won't be detected. |
Yeah this is kinda how I felt as well. I gave up on adding an auto region switch to the SMS core as a result thanks to your advice at the time then. Then maybe detecting it within the core just for those 19 PAL games in the last link from gpgx I provided would be easiest? It shouldn't use up a ton of registers to do this at such a small scale. It would default to NTSC video timings except for those 19 games. |
tl;dr probably still not worth it Using the same method to detect games I used here: https://github.com/MiSTer-devel/SMS_MiSTer/blob/master/SMS.sv#L554-L560 I came up with this simple code to do this just now if you wanted to try it out (would need to add a && sms_cart check or something like that, also might need a few other adjustments to even work, I haven't familiarized myself with the megadrive core's cart handling code yet): // Detect the different PAL timing SMS games released in Europe
if(ioctl_wr & cart_download) begin
if(ioctl_addr == 'h7ffc) cart_id[31:24] <= ioctl_dout[7:0];
if(ioctl_addr == 'h7ffd) cart_id[23:16] <= ioctl_dout[7:0];
if(ioctl_addr == 'h7ffe) cart_id[15:08] <= ioctl_dout[7:0];
if(ioctl_addr == 'h7fff) cart_id[07:00] <= ioctl_dout[7:0];
if(ioctl_addr == 'h8000) begin
if(cart_id == 32'h67_70_20_40) sms_pal <= 1; // Addams Family
else if(cart_id == 32'h20_70_20_40) sms_pal <= 1; // Back to the Future Part III
else if(cart_id == 32'h58_70_20_40) sms_pal <= 1; // Battlemaniacs (Brazil)
else if(cart_id == 32'h65_70_2F_40) sms_pal <= 1; // Bram Stoker's Dracula
else if(cart_id == 32'h05_71_00_40) sms_pal <= 1; // California Games II & Jogos de Varao II (Brazil)
else if(cart_id == 32'h09_71_00_40) sms_pal <= 1; // Home Alone
else if(cart_id == 32'h24_90_00_40) sms_pal <= 1; // Power Strike II
else if(cart_id == 32'h47_70_20_40) sms_pal <= 1; // Predator 2
else if(cart_id == 32'h19_25_00_40) sms_pal <= 1; // Quest for the Shaven Yak Starring Ren Hoek & Stimpy (Brazil)
else if(cart_id == 32'h64_70_20_40) sms_pal <= 1; // RoboCop 3
else if(cart_id == 32'h14_50_20_4f) sms_pal <= 1; // Sensible Soccer
else if(cart_id == 32'hff_ff_ff_4f) sms_pal <= 1; // Shadow of the Beast (FIRST DUPLICATE FOUND, this is a common unique id used in TONS of games, would be a false positive, almost all of them are Beta's/Samples/unreleased though)
else if(cart_id == 32'h73_25_00_40) sms_pal <= 1; // Sonic Blast (Brazil)
else if(cart_id == 32'h15_90_00_40) sms_pal <= 1; // Sonic the Hedgehog 2 (SECOND DUPLICATE FOUND, this is also used for Winter Olympics (Brazil) but no other games from no-intro)
else if(cart_id == 32'h15_90_01_40) sms_pal <= 1; // Sonic the Hedgehog 2 Rev 1
else if(cart_id == 32'h80_70_00_40) sms_pal <= 1; // Space Harrier (Europe)
else if(cart_id == 32'h38_70_00_40) sms_pal <= 1; // Taito Chase H.Q.
else if(cart_id == 32'h00_00_01_40) sms_pal <= 1; // Taito Chase H.Q. (Beta) & NBA Jam (Prototype)
end
end As you can see there are just two exceptions across the No-Intro SMS collection, that Shadow of the Beast's commercial release used the beta/sample/demo game ID that a bunch of other ones used that were never commercially released. So consider this a feasibility check to demonstrate some of the problems. The amount of hex read could be expanded to find out if there are ways to capture more hex values to make them all truly unique. The "unique" game id's were collected with the following python code: import os
import csv
def list_files(startpath):
"""Recursively list all files with the extensions .sms and .gg in the given path."""
file_list = []
for root, dirs, files in os.walk(startpath):
for file in files:
if file.endswith('.sms') or file.endswith('.gg'):
full_path = os.path.join(root, file)
file_list.append(full_path)
return file_list
def read_bytes_from_file(file_path, start_offset, end_offset):
"""Read and return bytes in hexadecimal from the given file between the specified offsets."""
with open(file_path, 'rb') as file:
file.seek(start_offset)
bytes_data = file.read(end_offset - start_offset)
return bytes_data.hex()
def save_to_csv(files_data, csv_filename):
"""Save the file data to a CSV."""
with open(csv_filename, 'w', newline='') as csvfile:
filewriter = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
filewriter.writerow(['File Path', 'Hex Data']) # Header
for file_data in files_data:
filewriter.writerow([file_data['path'], file_data['hex_data']])
def main():
"""Main function."""
current_directory = os.getcwd()
all_files = list_files(current_directory)
files_data = []
for file_path in all_files:
hex_data = read_bytes_from_file(file_path, 0x7ffc, 0x8000)
files_data.append({
'path': file_path,
'hex_data': hex_data
})
save_to_csv(files_data, 'hex_data.csv')
print(f"Hex data written to 'hex_data.csv' in the current directory.")
if __name__ == "__main__":
main() Resultant hex data file: |
I don't like this idea. There is no point to make it for 19 games only. You already provided enough info to understand there is no region inside SMS ROM. |
Yup, it's not a great solution. I definitely wasn't suggesting to go with it, it's too many registers and complexity added for just a few games when people in the PAL region generally know they need to switch to Europe manually already. :) |
Would it not be possible to at least make the core switch to PAL for Master System roms if it detects a different extension like say .smp same as the core already do for Genesis/Mega Drive games? |
it's possible. I don't know if there is a standard for extensions per region |
I don't think there is a "standard" per se, but the genesis and megadrive core set its region according to if you name the extensions to gen/md/bin which is not that standard also, but it works well to force the region for games. I have used it for a long time on MiSTer before it could even set the regions by looking at the header. |
gen/md extensions at least were exiting and tied to regions. |
Not sure if it is possible. Need to investigate it.
The text was updated successfully, but these errors were encountered: