2021-03-28 18:12:56 +01:00
2021-03-28 18:12:56 +01:00
2021-02-25 17:52:42 +00:00
2021-03-28 18:12:56 +01:00

Hiscores_MiSTer

This is a generic module for MiSTer arcade cores which enables high score save/load based on the MAME hiscore plugin data format (hiscore.dat).

Created by Alan Steremberg (alanswx)

Further development by Jim Gregory (JimmyStones)

Features

  • Reads hiscore.dat entries from MRA (defaults to ioctl index = 3)
  • Loads and saves high score data in <MRA name>.nvm dump (defaults to ioctl index = 4)
  • Configurable delay before high score load to game RAM
  • Configurable hold time during hiscore RAM read/write
  • Configurable single or double byte entry lengths
  • Pause signal to halt CPU for during multiplex with cores already using dual-port RAM

History

0001 - 2021-03-06

  • First marked release

0002 - 2021-03-06

  • Added HS_DUMPFORMAT localparam to identify dump version (for future use).
  • Add HS_CONFIGINDEX and HS_DUMPINDEX parameters to configure ioctl_indexes

0003 - 2021-03-10

  • Added WRITE_REPEATCOUNT and WRITE_REPEATDELAY to handle tricky write situations

0004 - 2021-03-15

  • Fix ram_access assignment

0005 - 2021-03-18

  • Add configurable score table width, clean up some stupid mistakes

0006 - 2021-03-27

  • Move 'tweakable' parameters into MRA data header

Implementation instructions

  • Add hiscore.sv to rtl/ folder and files.qip
  • Add the following code to the main core .sv file.
// HISCORE SYSTEM
// --------------

wire [15:0]hs_address;
wire [7:0]hs_data_in;
wire hs_write;
wire hs_access;

hiscore #(
	.HS_ADDRESSWIDTH(16),
	.CFG_ADDRESSWIDTH(4)
) hi (
	.clk(clk_sys),
	.reset(reset),
	.ioctl_upload(ioctl_upload),
	.ioctl_download(ioctl_download),
	.ioctl_wr(ioctl_wr),
	.ioctl_addr(ioctl_addr),
	.ioctl_dout(ioctl_dout),
	.ioctl_din(ioctl_din),
	.ioctl_index(ioctl_index),
	.ram_address(hs_address),
	.data_to_ram(hs_data_in),
	.ram_write(hs_write),
	.ram_access(hs_access)
);

The module parameters in the example above are the bare minimum config required to customise behaviour for a core. See Module parameters for further details.

Core specific implementation

NOTE: It is advisable to implement a working pause system beforehand so the hs_access can be used to pause the core while reading/writing to game RAM to avoid instability/corruption.

Add code to link the high score signals into the relevant RAM instances.

In simple cases (see Phoenix core for an example) this will only involve converting a working RAM instance from single to dual port.

If hiscores are located in multiple RAM areas then some multiplexing will be needed to merge/split based on hs_address.

If RAM is already dual-ported then the access signal should be used to pause CPU and switch inputs to one of the ports during highscore access (see Sega System 1 for a particularly complex example!)

Module parameters

Parameters should be configured to allow the high score system to cope with all games supported by the core. Maximum dump size, maximum number of entries and largest individual entry length need to be collated for all MRAs before selecting values.

Parameter Description
HS_ADDRESSWIDTH Set to the widest memory address used by the core. The upper size of hs_address should should be set to the same -1.
HS_SCOREWIDTH Set to allow the size of the largest .nvm dump for this core (default is 8, allowing 256 bytes)
HS_CONFIGINDEX Optional override of ioctl_index used for config download (default is 3)
HS_DUMPINDEX Optional override of ioctl_index used for nvram dump download (default is 4)
CFG_ADDRESSWIDTH Set to allow for the maximum number of hiscore.dat entry lines used by the core (e.g. 4 = 16 max)
CFG_LENGTHWIDTH Set to 1 for single byte length, 2 for double

Module ports

Port Direction Description
clk in System clock. Should match the HPS IO clock input
reset in Active-high reset signal from core
ioctl_upload in From HPS module
ioctl_download in From HPS module
ioctl_wr in From HPS module
ioctl_addr in From HPS module
ioctl_dout in From HPS module
ioctl_din in From HPS module
ioctl_index in From HPS module
ram_address out System RAM address for highscore read/write
data_to_ram out Data to write to system RAM
ram_write out Active-high signal to write to system RAM
ram_access out Active-high signal used to pause CPU

MRA data

To enable the high score module add the following sections to the MRA.

MRA sections

<rom index="3" md5="none">
	<part>
		00 00 FF FF 00 FF 00 02 00 02 00 01 11 11 00 00
		00 00 90 5F 01 30 30 00 
		00 00 90 7F 01 30 30 00 
		00 00 90 9F 01 30 30 00 
		00 00 90 BF 01 30 30 00 
		00 00 90 DE 03 53 24 00 
		00 00 90 FE 03 2D 24 00 
		00 00 91 1F 01 00 00 00 
		00 00 91 3F 01 00 00 00 
		00 00 80 E2 04 00 00 00 
		00 00 81 00 96 00 FF 00 
	</part>
</rom>
<nvram index="4" size="166"/>

The <rom index="3"> section contains a header section with runtime tweakable parameters, and the entries from the MAME hiscore.dat file.

Header data
Size (bytes) Parameter Description
4 START_WAIT Number of cycles before beginning check process (usually 0)
2 CHECK_WAIT Number of cycles to wait between start/end checks (usually 256)
2 CHECK_HOLD Number of cycles to wait during start/end checks to allow addresses/multiplexers to settle (usually 2)
2 WRITE_HOLD Number of cycles to wait during write to game RAM to allow addresses/multiplexers to settle (usually 2)
2 WRITE_REPEATCOUNT Number of times to write score to game RAM - used to brute force cores that don't behave (usually 1)
2 WRITE_REPEATWAIT Number of cycles delay between subsequent write attempts (usually 16)
2 (padding/future use)
Entry data

If CFG_LENGTHWIDTH=1 then the following structure is used:

  • 4 bytes Address of ram entry (in core memory map)
  • 1 byte Length of ram entry in bytes
  • 1 byte Start value to check for at start of address range before proceeding
  • 1 byte End value to check for at end of address range before proceeding
  • 1 byte (padding)

Below is the original hiscore.dat entry for the example above (Bomb Jack)

@:maincpu,program,905f,1,30,30
@:maincpu,program,907f,1,30,30
@:maincpu,program,909f,1,30,30
@:maincpu,program,90bf,1,30,30
@:maincpu,program,90de,3,53,24
@:maincpu,program,90fe,3,2d,24
@:maincpu,program,911f,1,00,00
@:maincpu,program,913f,1,00,00
@:maincpu,program,80e2,4,00,00
@:maincpu,program,8100,96,00,ff

If CFG_LENGTHWIDTH=2 then the following structure is used:

  • 4 bytes Address of ram entry (in core memory map)
  • 2 byte Length of ram entry in bytes
  • 1 byte Start value to check for at start of address range before proceeding
  • 1 byte End value to check for at end of address range before proceeding

The size attribute in <nvram index="4" size="?"> should be the decimal total of all lengths in the entry table.

Notes

Multiplexing

For cores which require multiplexing due to scores being split across multiple RAM banks, or where RAM is already dual-ported, the active-high hs_access signal is triggered while the high score module is reading or writing game RAM.

Calculating delays

Delays should be calculated based on the clock passed to the hiscore module - e.g. for a 48MHz clock, a 10 second delay should be 48 * 1000 * 1000 * 10 = 31'h1C9C3800;

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Description
No description provided
Readme GPL-3.0 100 KiB
Languages
Verilog 100%