What's new
Whether or not the original battery was used for that. I think the real question is... how do we make score saving work on all of those Raiden 2 and Raiden DX boards out there?
 
I would start by trying the various MAME sets, getting into the hiscore table and inspecting nvram afterwards.
 
My board saved hiscores, I disconnected the battery , put a new one and the hiscore was not saved anymore. I then reconnected the old one and still no save.
Definitely when you disconnect the battery you loose some bytes used to save hiscores.
 
My copy had the battery disconnected when it was shipped to me. Doesn't matter if it's connected or not, no scores saved.
 
If we're really serious about cracking this nut this is what needs to be done:
-trace the battery positive to see what it's powering on the PCB
-lookup the data sheets for the devices being powered.
-trace out the address of the devices being powered
-look at the mame driver for what is mapped to that address
-run the game in debug mode and trace reads/writes to that address.

alternatively we can start in the other direction
-using mame in debug mode identify where in memory highscores are being written
-trace back to code that writes to those locations and step through to see if additional writes are being performed and where
-if additional writes or logic around high scores is happening outside of main RAM then identify what address and where
-determine what physical devices are attached to those addresses.
 
ok so cracked open MAME set a high score,
raiden_2_high_score_CHH.png


before choosing my initials I found a string of characters that returned no results when searching memory.

after entering initials "CHH" found exactly one instance in memory within the main memory at location 09E48

converting my "21800" high-score to hex I get "55 28" which I also found near by 09E46
raiden_2_high_score_MEM.png


it looks a little screwy because it's byte swapped but MAME doesn't retain highscores in this game between sessions and I was able to set a different score for place 10 and have it appear here as well.
this also implies that the behavior of not saving the high score is how mame functions.

looking at this area a little further we can see that the default scores while displaying "xxx" are actually stored as "***", and there are two high score tables, one for solo player and one for dual players

raiden_2_high_score_MEM2.png


The next step would be identifying where in code reads and writes to this memory location during boot, where presumably there is some code that reads from backup and writes into main memory.
 
Last edited:
poking at this from the other end. I've got a Raiden II with a battery (which is dead flat).
Tracing the battery positive it goes through Resistor R107 then through Diode D0715
from there it splits off and its D0716 and C072 which are both tied to ground on the other side, and it also goes to the SEI252 SB05-106 Custom

SEI252 is a large QFP graphics decryption chip looking at the mame driver it actually mentions that on the Zero Team variant that came on this board, this custom stored the graphics decryption keys that would be written to memory on boot, and if the battery dies (on Zero Team) the graphics become corrupted. There is also a "revival" ROM set to restore the keys after a battery replacement, as well as a set that functions without a battery by writing the keys to memory on boot from the ROMs rather than this custom.

checking the battery power routing I don't see where it's routed to power any of the RAM chips on the PCB... only this custom.
pins 10, 11, 43, 62, 82, 97, 98,114, 147, 165, 201 appear to all be connected to battery
battery_path.png


so this leads me to believe that either the high scores are intended to be saved on the graphics decryption custom, or they couldn't ever be saved because there is no other non-volatile location on the PCB anywhere.
 
Last edited:
Thank you for looking into this @twistedsymphony. Is there a memory map in MAME which includes the SEI252 address space ? Or maybe this area is mirrored ? Alternately we are looking for a test which checks a value and explicitly uploads/copies data. @kold666 do you remember if the entire hiscore table was saved or just the top 3 ?
 
Is there a memory map in MAME which includes the SEI252 address space
yes but it's not simple. Assuming the SEI252 is the "COP" protection device there's a whole map function just for that.

Code:
/* MEMORY MAPS */
void raiden2_state::raiden2_cop_mem(address_map &map)
{
	map(0x0041c, 0x0041d).w(m_raiden2cop, FUNC(raiden2cop_device::cop_angle_target_w)); // angle target (for 0x6200 COP macro)
	map(0x0041e, 0x0041f).w(m_raiden2cop, FUNC(raiden2cop_device::cop_angle_step_w));   // angle step   (for 0x6200 COP macro)
	map(0x00420, 0x00421).w(m_raiden2cop, FUNC(raiden2cop_device::cop_itoa_low_w));
	map(0x00422, 0x00423).w(m_raiden2cop, FUNC(raiden2cop_device::cop_itoa_high_w));
	map(0x00424, 0x00425).w(m_raiden2cop, FUNC(raiden2cop_device::cop_itoa_mode_w));
	map(0x00428, 0x00429).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_v1_w));
	map(0x0042a, 0x0042b).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_v2_w));
	map(0x0042c, 0x0042d).w(m_raiden2cop, FUNC(raiden2cop_device::cop_prng_maxvalue_w));
	map(0x00432, 0x00433).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pgm_data_w));
	map(0x00434, 0x00435).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pgm_addr_w));
	map(0x00436, 0x00437).w(m_raiden2cop, FUNC(raiden2cop_device::cop_hitbox_baseadr_w));
	map(0x00438, 0x00439).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pgm_value_w));
	map(0x0043a, 0x0043b).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pgm_mask_w));
	map(0x0043c, 0x0043d).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pgm_trigger_w));
	map(0x00444, 0x00445).w(m_raiden2cop, FUNC(raiden2cop_device::cop_scale_w));
	map(0x00450, 0x00451).w(m_raiden2cop, FUNC(raiden2cop_device::cop_sort_ram_addr_hi_w));
	map(0x00452, 0x00453).w(m_raiden2cop, FUNC(raiden2cop_device::cop_sort_ram_addr_lo_w));
	map(0x00454, 0x00455).w(m_raiden2cop, FUNC(raiden2cop_device::cop_sort_lookup_hi_w));
	map(0x00456, 0x00457).w(m_raiden2cop, FUNC(raiden2cop_device::cop_sort_lookup_lo_w));
	map(0x00458, 0x00459).w(m_raiden2cop, FUNC(raiden2cop_device::cop_sort_param_w));
	map(0x0045a, 0x0045b).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pal_brightness_val_w)); //palette DMA brightness val, used by X Se Dae / Zero Team
	map(0x0045c, 0x0045d).w(m_raiden2cop, FUNC(raiden2cop_device::cop_pal_brightness_mode_w));  //palette DMA brightness mode, used by X Se Dae / Zero Team (sets to 5)
	map(0x00470, 0x00471).rw(FUNC(raiden2_state::cop_tile_bank_2_r), FUNC(raiden2_state::cop_tile_bank_2_w)); // implementaton of this varies between games, external hookup?

	map(0x00476, 0x00477).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_adr_rel_w));
	map(0x00478, 0x00479).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_src_w));
	map(0x0047a, 0x0047b).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_size_w));
	map(0x0047c, 0x0047d).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_dst_w));
	map(0x0047e, 0x0047f).rw(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_mode_r), FUNC(raiden2cop_device::cop_dma_mode_w));
	map(0x004a0, 0x004ad).rw(m_raiden2cop, FUNC(raiden2cop_device::cop_reg_high_r), FUNC(raiden2cop_device::cop_reg_high_w));
	map(0x004c0, 0x004cd).rw(m_raiden2cop, FUNC(raiden2cop_device::cop_reg_low_r), FUNC(raiden2cop_device::cop_reg_low_w));
	map(0x00500, 0x00505).w(m_raiden2cop, FUNC(raiden2cop_device::cop_cmd_w));
	map(0x00580, 0x00581).r(m_raiden2cop, FUNC(raiden2cop_device::cop_collision_status_r));
	map(0x00582, 0x00587).r(m_raiden2cop, FUNC(raiden2cop_device::cop_collision_status_val_r));
	map(0x00588, 0x00589).r(m_raiden2cop, FUNC(raiden2cop_device::cop_collision_status_stat_r));
	map(0x00590, 0x00599).r(m_raiden2cop, FUNC(raiden2cop_device::cop_itoa_digits_r));
	map(0x005a0, 0x005a7).r(m_raiden2cop, FUNC(raiden2cop_device::cop_prng_r)); // zeroteam reads from 5a4
	map(0x005b0, 0x005b1).r(m_raiden2cop, FUNC(raiden2cop_device::cop_status_r));
	map(0x005b2, 0x005b3).r(m_raiden2cop, FUNC(raiden2cop_device::cop_dist_r));
	map(0x005b4, 0x005b5).r(m_raiden2cop, FUNC(raiden2cop_device::cop_angle_r));

	map(0x00600, 0x0063f).rw("crtc", FUNC(seibu_crtc_device::read), FUNC(seibu_crtc_device::write));
	//map(0x00640, 0x006bf).rw("obj", FUNC(seibu_encrypted_sprite_device::read), FUNC(seibu_encrypted_sprite_device::write));
	map(0x006a0, 0x006a3).w(FUNC(raiden2_state::sprcpt_val_1_w));
	map(0x006a4, 0x006a7).w(FUNC(raiden2_state::sprcpt_data_3_w));
	map(0x006a8, 0x006ab).w(FUNC(raiden2_state::sprcpt_data_4_w));
	map(0x006ac, 0x006af).w(FUNC(raiden2_state::sprcpt_flags_1_w));
	map(0x006b0, 0x006b3).w(FUNC(raiden2_state::sprcpt_data_1_w));
	map(0x006b4, 0x006b7).w(FUNC(raiden2_state::sprcpt_data_2_w));
	map(0x006b8, 0x006bb).w(FUNC(raiden2_state::sprcpt_val_2_w));
	map(0x006bc, 0x006bf).w(FUNC(raiden2_state::sprcpt_adr_w));
	map(0x006c0, 0x006c1).rw(FUNC(raiden2_state::sprite_prot_off_r), FUNC(raiden2_state::sprite_prot_off_w));
	map(0x006c2, 0x006c3).rw(FUNC(raiden2_state::sprite_prot_src_seg_r), FUNC(raiden2_state::sprite_prot_src_seg_w));
	map(0x006c4, 0x006c5).nopw(); // constant value written along with 0x6c0
	map(0x006c6, 0x006c7).w(FUNC(raiden2_state::sprite_prot_dst1_w));
	map(0x006cb, 0x006cb).w(FUNC(raiden2_state::raiden2_bank_w));
	map(0x006cc, 0x006cc).w(FUNC(raiden2_state::tile_bank_01_w));
	map(0x006ce, 0x006cf).w(FUNC(raiden2_state::sprcpt_flags_2_w));
	map(0x006d8, 0x006d9).w(FUNC(raiden2_state::sprite_prot_x_w));
	map(0x006da, 0x006db).w(FUNC(raiden2_state::sprite_prot_y_w));
	map(0x006dc, 0x006dd).rw(FUNC(raiden2_state::sprite_prot_maxx_r), FUNC(raiden2_state::sprite_prot_maxx_w));
	map(0x006de, 0x006df).w(FUNC(raiden2_state::sprite_prot_src_w));
	/* end video block */

	map(0x006fc, 0x006fd).w(m_raiden2cop, FUNC(raiden2cop_device::cop_dma_trigger_w));
	map(0x006fe, 0x006ff).w(m_raiden2cop, FUNC(raiden2cop_device::cop_sort_dma_trig_w)); // sort-DMA trigger

	map(0x00762, 0x00763).r(FUNC(raiden2_state::sprite_prot_dst1_r));
}

There's a lot there and I don't know what it all does though it does seem to all be graphics related. There is also quite a few gaps in what's mapped in this memory space and the area we're looking for could have been missed and is hiding in one of them.

one thing that did stick out to me on the Raiden DX map is this:

Code:
map(0x004d0, 0x004d7).ram(); //???
that address seems to be right in the middle of the COP area... though looking at the size of the high score tables. both tables together are 240 (0xF0) bytes in size which seems to be smaller than that address.

I'd be curious if anyone has an original Battery-Backed Zero Team board and could see if high-scores save, that would ensure that this device has appropriate data stored on it.

The fact that in later releases they retained the battery but stopped storing codes here leads credence to this being used for storing of high scores. though I'm guessing there is some logic that looks to see if the area is prepaired or is empty and uses RAM instead of the custom if it see the code missing.

another thing we could try is replacing the battery on one of these units and using the Zero team revive code to either populate it with Zero team data or just filled with 0xFF or something so that the device appears prepaired even if the data is bad.
 
Maybe the area has to be checksummed before writing to it ?
 
I tried monitoring reads from the COP region and got nothing, it pops a read to 0x0470 every frame but that's it, even from boot.

monitoring the region of memory where I found the high score table was interesting. right at the start of boot there's a command that seems to write all 0s to the region
command at PC 98056
aword.png


shortly after that at PC 99E57 we see it start to write the default high score table with the 50,000 point value (0xC350 in hex)
50000.png

This section of code though is just a loop, it starts at 50000 and subtracts 4000 and sets the score name to *** on every loop until it completes the list. There are two such loops one for each table.

not really what we're looking for but at least we now understand that the default table is built and not just copied in from some place.
 
Last edited:
It looks to me you found the initialization, question is, how is it called service menu?
Maybe creating a (2) patched EPROM(s) that jump directly to this code fix the issue.
After that you place the original ROMs and it works again?
 
Last edited:
This is fascinating reading.

I've had my Raiden 2 board with the original battery on it for 10-15 years now and it's never saved a score at all. Following this with great interest! :)
 
Back
Top