Can a modchip/custom BIOS theoretically report Game ID to a Memcard Pro?

General information to do with the PlayStation 1 Hardware. Including modchips, pinouts, rare or obscure development equipment, etc.
User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Can a modchip/custom BIOS theoretically report Game ID to a Memcard Pro?

Post by bobrocks95 » September 27th, 2022, 11:37 am

I'm frustrated that the current solution for a slim PS One + Memcard Pro's automatic Game ID-based page creation requires using FreePSXBoot and UniROM to pull the Game ID from an actual disc. That requires the somewhat lengthy FreePSXBoot sequence of starting the system with the lid open, starting the Memory Card Manager up, waiting for UniROM to load into memory, and then closing your lid and starting the game. Plus there's the potential for compatibility issues with UniROM and possibly Tonyhax as well (which as far as I know does not report the Game ID to the Memcard Pro anyways).

Considering the SYSTEM.CNF file on-disc contains the ID string and is required for booting, is it theoretically possible for a modchip to read that data and report it to the Memcard Pro in the same way that UniROM does?

Unfortunately UniROM's code is not publicly available yet, so I'm unsure of how complex Memcard Pro integration is. Chriz from PixelFX has a public writeup available detailing the commands to send Game ID, which seem simple but it's very easy for me to armchair speculate on work I haven't done myself.

What do you all think? Never again having to even think once about organizing my memory cards is my end goal, and XStation users are already there with Memcard Pro integration. Can we get there with retail discs too?

EDIT: A custom BIOS could be another possibility if a modchip is not feasible?

EDIT2: Re-reading I also want to make it clear that I'm not trying to knock UniROM or FreePSXBoot. It's incredible that a softmod that can play backups and defeat region protection is available for the PS1 at all. I'm just wondering if, via hardware modification, the experience can be improved over a (bit slow for someone with a modchip already) pure software solution.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » September 28th, 2022, 4:08 am

You want to forward the game ID from SYSTEM.CNF to memory card? Yes, of course that's possible.

Do you have any documentation or source code showing what exactly is to be written to the memory card?

With a custom BIOS it would be no problem. One could easily patch the official BIOS, or I could also implement it in my BIOS clone. Either way, it would require soldering (at least so on newer consoles without expansion part).

Mod chips rather won't work (unless you have some huge mod chip that can be wired to the whole 8bit BIOS data bus).

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » September 28th, 2022, 11:01 am

nocash wrote: September 28th, 2022, 4:08 am You want to forward the game ID from SYSTEM.CNF to memory card? Yes, of course that's possible.

Do you have any documentation or source code showing what exactly is to be written to the memory card?

With a custom BIOS it would be no problem. One could easily patch the official BIOS, or I could also implement it in my BIOS clone. Either way, it would require soldering (at least so on newer consoles without expansion part).
Oh hey, nocash, hope you're doing well and got some relief on the living situation.

chriz2600 has a comprehensive writeup on sending the GameID, it looks like some simple raw commands to the memory card/controller bus: https://gitlab.com/chriz2600/ps1-game-i ... /README.md.

I am not quite sure if the DAT/ACK lines provide anything useful back from the MemCard Pro. I wouldn't think you'd have to even ping to check if the MemCard Pro is present or not, just blast out the required Game ID string to both memory card ports and call it a day. Unless sending these commands could potentially cause problems if one is not actually present (your documentation if I'm understanding right says the operation is aborted if the second command byte isn't "R", "W", or "S" in hex).

I have two slim PSOne's, but I'm fine with SMD soldering and can easily test a replacement, though I might have to request a vendor to flash a custom version for me beforehand or buy a programmer. I'd prefer modifying the official BIOS if you can point me towards tools to do so, but hey if you feel like putting in the work for it I'll take what I can get and switch to PSX-XBOO!
Mod chips rather won't work (unless you have some huge mod chip that can be wired to the whole 8bit BIOS data bus).
This was the detail I was missing and makes perfect sense. I think some Arduino ATmega based boards have enough spare GPIO available, but if the BIOS data bus is what communicates with the CD Controller or memory card bus anyways, it makes much more sense to replace the BIOS.

EDIT: Well it seems BIOS decompilation is not as far along as I would have thought. I did find some progress from here and have it open in IDA Pro with some insights... a ParseConfig function as they call it that does look like it cleanly pulls in BOOT, TCB, EVENT, and STACK from SYSTEM.CNF, not sure exactly where they're stored in registers/on the stack though, or how modifying the BIOS code goes (is it checksummed? Is there empty space to remove when adding instructions?). It's going to take a bit to learn MIPS assembly!

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » September 29th, 2022, 6:50 pm

This is the kernel function for reading the ID aka "boot_exe_name". The code may be slightly different in other kernel versions.

Code: Select all

                 ;------------------
                 decipher_system_cnf:
                  ;in: r4=sector_buffer, r5=boot_cnf_values, r6=boot_exe_name
BFC008A0 27BDFFD8 sub     sp,28h
BFC008A4 AFA40028 mov     [sp+28h],r4 ;=sector_buffer
BFC008A8 AFBF0024 mov     [sp+24h],ra
BFC008AC AFA60030 mov     [sp+30h],r6 ;=boot_exe_name
BFC008B0 24040003 mov     r4,3h       ;end (3 words)    ;BFC008B4 00001021 mov     r2,0        ;index            ;
BFC008B8 00A01821 mov     r3,r5 ;=boot_cnf_values       ;
                 @@fill_lop:                            ; zerofill [boot_cnf_values+0..0Bh]
BFC008BC 24420001 add     r2,1h       ;index            ;
BFC008C0 AC600000 mov     [r3],0      ;dst              ;
BFC008C4 1444FFFD jne     r2,r4,@@fill_lop ;\           ;
BFC008C8 24630004 + add   r3,4h       ;dst ;/           ;/
BFC008CC 8FAE0030 mov     r14,[sp+30h] ;=boot_exe_name  ;BFC008D0 3C06BFC1 mov     r6,0BFC10000h                 ; [boot_exe_name]=00h
BFC008D4 A1C00000 movb    [r14],0   ;[boot_exe_name]=00h;/
BFC008D8 8FA40028 mov     r4,[sp+28h]  ;=sector_buffer  ;BFC008DC A0000180 movb    [180h],0  ;[boot_cmdline]=00h ; <--- clear cmdline
BFC008E0 AFA5002C mov     [sp+2Ch],r5;=boot_cnf_values  ;
                 ;mov     r5,r5      ;=boot_cnf_values+0; TCB = hex
BFC008E4 0FF00251 call    get_numeric_cnf_line          ;
BFC008E8 24C6DD10 + sub   r6,22F0h   ;=txt_tcb          ;/
BFC008EC 8FA5002C mov     r5,[sp+2Ch];=boot_cnf_values  ;BFC008F0 8FA40028 mov     r4,[sp+28h];=sector_buffer    ; EVENT = hex
BFC008F4 3C06BFC1 movp    r6,txt_event                  ;
BFC008FC 0FF00251 call    get_numeric_cnf_line          ;
BFC00900 24A50004 + add   r5,4h      ;=boot_cnf_values+4;/
BFC00904 8FA5002C mov     r5,[sp+2Ch];=boot_cnf_values  ;BFC00908 8FA40028 mov     r4,[sp+28h];=sector_buffer    ; STACK = hex
BFC0090C 3C06BFC1 movp    r6,txt_stack                  ;
BFC00914 0FF00251 call    get_numeric_cnf_line          ;
BFC00918 24A50008 + add   r5,8h      ;=boot_cnf_values+8;/
BFC0091C 8FA40028 mov     r4,[sp+28h]  ;=sector_buffer  ;BFC00920 8FA50030 mov     r5,[sp+30h]  ;=boot_exe_name  ; BOOT = string
BFC00924 3C07BFC1 movp    r7,txt_boot                   ; (via other subfunc)
BFC0092C 0FF002DF call    get_boot_file_arg_cnf_line    ;
BFC00930 24060180 + mov   r6,00000180h ;=boot_cmdline   ;/
BFC00934 8FBF0024 mov     ra,[sp+24h]
BFC00938 27BD0028 add     sp,28h
BFC0093C 03E00008 ret
BFC00940 00000000 + nop
It may best to patch that function and redirect it to some code that is sending the ID to memory card. There should be some unused memory between bios code and bios character set region, and the charset region does also contain some unused garbage: http://problemkaputt.de/psxspx-bios-character-sets.htm

For assembling/disassembling code I would use my own tools (the assemble/disassemble functions in no$psx "utility" menu). A source code example is here: http://www.psxdev.net/forum/viewtopic.php?t=1317 well, that's rather large (I should probably make a smaller example). The vcd source code doesn't seem to have memory card functions... but it does have joypad functions (which are similar).

The assembler can also use a .import directive (alike INCBIN in other assemblers) to import binary code from the original bios rom file, so you could make kernel patches like this:

Code: Select all

org 0BFC00000h
.import bios.rom offset,len
(insert some custom asm code here)
.import bios.rom offset2,len2
(insert some custom asm code here)
.import bios.rom offset3,len3
.end
For testing memcard functions on hardware, you are probably better of when first using an EXE file before doing ROM patches (if you can run EXE files without burning CDRs). Or test normal memory card access in emulators before doing the game id transfer on hardware.

PS. Yeah, I am still homeless... but the patreon donations somehow went up massively last month, that's quite a relief and I am much more optimistic about the future.

PPS. Direct link
https://gitlab.com/chriz2600/ps1-game-i ... /README.md
Last edited by nocash on October 5th, 2022, 9:06 pm, edited 1 time in total.

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » September 30th, 2022, 6:22 pm

What's the best way to get to the "BFC" BIOS code section in the no$psx debugger? Goto... doesn't want to take me there, I had to resort to searching for a string I knew was in the BIOS and then scrolling up really far to get to BFC008A0.

My findings so far are:
- Zeroing out/nop'ing 0xBFC65CB6 - 0xBFC66000 seems to leave the BIOS operating fine, so it should all be usable for these purposes, and hopefully large enough.
- The boot string is fully in memory at 0x0020B070 at the time the function for processing the system.cnf starts. I don't know if I'm making it harder on myself trying to just pull that out of memory and not taking advantage of the existing function. I don't normally program in assembly so my thought process of "just pull it out of memory" may not be correct. Maybe I'll try some C to general MIPS compilation and then tweak from there?

Is sending commands to the controller port as simple as writing the data to 0x1F801040, I guess 1 byte at a time in a loop since bits 9-32 aren't used? I see stuff with buffers so maybe I'm grossly oversimplifying it.


And are the .import directives just for making the final BIOS insertion easier using the assembler? Feed it properly formatted assembly and each .import command will put that assembly where I tell it to without me having to manually hex-edit all the values in?

User avatar
Shadow
Verified
Admin / PSXDEV
Admin / PSXDEV
Posts: 2600
Joined: Dec 31, 2012
PlayStation Model: H2000/5502
Discord: Shadow^PSXDEV

Post by Shadow » September 30th, 2022, 9:06 pm

CTRL+G to jump to an address in NO$PSX and enter the address as hexadecimal without the leading '0x' prefix.
Development Console: SCPH-5502 with 8MB RAM, MM3 Modchip, PAL 60 Colour Modification (for NTSC), PSIO Switch Board, DB-9 breakout headers for both RGB and Serial output and an Xplorer with CAETLA 0.34.

PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » October 1st, 2022, 11:31 am

Shadow wrote: September 30th, 2022, 9:06 pm CTRL+G to jump to an address in NO$PSX and enter the address as hexadecimal without the leading '0x' prefix.
Surely I'm missing something obvious?


Image
Image

Like I said before my current solution is to search for a debug string ("KERNEL SETUP!") and then scroll from there, which takes quite awhile

Image

User avatar
Shadow
Verified
Admin / PSXDEV
Admin / PSXDEV
Posts: 2600
Joined: Dec 31, 2012
PlayStation Model: H2000/5502
Discord: Shadow^PSXDEV

Post by Shadow » October 1st, 2022, 10:16 pm

Okay, I was incorrect. You do need to add the '0x' prefix for it to work :)
Development Console: SCPH-5502 with 8MB RAM, MM3 Modchip, PAL 60 Colour Modification (for NTSC), PSIO Switch Board, DB-9 breakout headers for both RGB and Serial output and an Xplorer with CAETLA 0.34.

PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » October 1st, 2022, 10:36 pm

Entering hex values starting with 0-F require leading 0 to distinguish from symbols starting with A-Z.

Pulling the string out of memory works only if it was already put into memory, it's good to know if/when/where it was put into memory.

Import does import original binary data portions (not assembler source code), but yes, the idea is to merge the original and patched data without needing to do that manually via hex editor.

As far as I remember, joypad and memcard access differ only by first byte (01h or 81h), the data is transferred byte by byte, no matter if the bytes are stored in a buffer.
Last edited by nocash on October 5th, 2022, 10:57 pm, edited 1 time in total.

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » October 2nd, 2022, 2:01 pm

That did the trick for accessing those regions in the editor.

And misspoke slightly on the .import function, of course it's going to convert it to binary first, point is avoiding painstaking manual hex editing work so that's good.

I'm having some trouble with the import command though- if I assemble through no$psx should I be able to immediately see the opcodes inserted into the code/data windows at the specified org+offset? And is len in bytes, so 4 * number of assembly lines?

Minimal example adapted from the vblank.asm source- should I see this inserted at 0xBFC65CB8? And is this even remotely close for a TTY output printf lol (assuming it will be called in the middle of BIOS running when TTY has already been enabled)

Code: Select all

org 0BFC00000h
.import PSX-BIOS.ROM 0x065CB8,24
    la     r4, LC0
    addiu  r10,zero,0x00a0
    jr     r10
    addiu  r9,zero,0x003f
    nop

LC0:    db "Hello World!\n"
Sorry for noobish assembly questions, most I've done is a small amount of x86 assembly back in college.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » October 2nd, 2022, 7:11 pm

All offsets are in bytes.
ORG is the start offset in the PSX memory space.
The IMPORT offset is a fileoffset within the imported file, starting at 0.

You may need something like +/-base if you want to convert file offsets to PSX memory offsets, or vice versa.

If no$psx does recognize the resulting binary as ROM image then it should immediately show up in memory after assembling the file. For a EXE it should should show up once when loading the EXE from cdrom. If it doesn't show up: Use a hex editor to look what was written into your binary file.

Ah, I forgot, for a ROM image, add directive .bios at the begin of the source code.
Directives .auto_nop and .nocash may be also useful if you want to tweak the asm syntax, or leave them out if you are fine with official MIPS syntax.

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » October 3rd, 2022, 3:29 pm

So it's assembling properly, creating a .ROM instead of a .EXE, it's just always getting appended to the end of the generated ROM image. Offset and len don't seem to do much of anything...

Am I misunderstanding the purpose of the .import function? I want to take the assembly code below .import, and put it into the ROM at the specified address/offset. "Shove this code here and calculate the branch addresses" essentially. I'm starting to think maybe .import is just pulling in PSX-BIOS.ROM in it's entirety, and then I'm just adding assembly onto the end of it...

Even so,

Code: Select all

.import PSX-BIOS.ROM 100,200
doesn't import 200 bytes from PSX-BIOS.ROM, skipping the first 100 bytes, it just throws the whole file in.

So far I'm able to test my entry point by manually copying hex values to the actual PSX-BIOS.ROM file from the Hello World test (I got TTY output which is cool!), but I'm of course not quite using the tools properly.


EDIT: More pressing concern- this sra instruction is being interpreted as a db variable???

Image

Code: Select all

BFC65E00 00000000        nop
BFC65E00 25290001        addiu   r9,r9,1
BFC65E04 000A5600        sll     r10,r10,18h
BFC65E08 000A5603        sra     r10,r10,18h    ; Instruction misread as db???
Nothing but db destroying all the opcodes past that sra line. Right click -> Change Instruction will take a properly formatted opcode but will not change the line at all.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » October 3rd, 2022, 9:08 pm

Oops, I've got the above import example wrong: There must be a comma between filename and offset. Sorry!

For the data lines, the binary values are looking okay, so the emulator should execute the shift opcode correctly, no matter if the disassembler is showing it as data or not.
No$psx contains a list with known data fields for different kernel versions, the CEX-3000/7000 kernel has some data at 0bfc65e0ch and 0bfc65e20h, it's probably just dummy/garbage data, but no$psx does display it as data field.
So that's getting wrong with patched kernels that store something else in those data fields. If needed, you can toggle it off by going to the begin of the data field and press Ctrl+D.

Btw. is it required to use the small garbage memory snippet in the charset region? Most kernels seem to have a lot of unused zerofilled memory in front of the charset region.

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » October 4th, 2022, 2:37 pm

Things are going fairly smoothly now, thanks for everything so far nocash!

Is there a simple way to zerofill n number of bytes after my assembly? Or even better, a way to calculate how many bytes to be zero-filled? (Number of bytes of empty memory available (known) - size of assembly in bytes (calculated) = n bytes to zerofill)? This isn't too bad to do manually compared to checking addresses and all that, so it's not a huge deal.

EDIT: Found the .align 800h in your VCD source which happened to be exactly how much I needed to pad, assembling is totally automatic now! :D

I will replace this with a silly question of how to properly terminate my strings for TTY output with newlines in-between to make my debug output look a little nicer haha

Code: Select all

LC0:    db "Building bootstring\n",0
LC1:    db "bootstring built- %s\n",0
(this just prints the '\n' to the output- \r\n isn't working either it seems)
nocash wrote: October 3rd, 2022, 9:08 pmBtw. is it required to use the small garbage memory snippet in the charset region? Most kernels seem to have a lot of unused zerofilled memory in front of the charset region.
It doesn't matter to me where the code is located, do you think I should use the memory in front of the charset region instead of in the middle of it? I opted to load the "payload" by replacing a nop in the function that reads the boot string so I should be able to jump anywhere (if there's a distance limit when encoding a single-line branch I didn't hit it).

Ideally if I actually get this working it would be good for it to be as compatible as possible (though I am personally only interested in getting it working on my SCPH-101 console).

EDIT2: Assembling is fully automated as of tonight with the injection not affecting anything else, that's a win in my book. Hopefully actually writing the data to the memory card port isn't too bad lol. Gotta remember to test Wild Arms' weird boot string too. I can improve my code drastically now that I understand better as well, though I'll leave refactoring until I've finished I suppose.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » October 4th, 2022, 10:39 pm

Cool, I was afraid that I might have steered you into troubles when suggesting to use the no$psx asm tools.

Yes, .align works for zerofill, or "defs numbytes" does also zerofill, or ".import name,offs,numbytes" does "fill" with original data.
You can also use labels (like the LC0 one you have in your code) to compute such offs and numbytes values. And $ is short for the current address. Mind that the labels and $ are in the BFC00000h memory space defined with ORG. Two examples:
defs 0BFC66000h-$ ;zerofill
.import name, $-0BFC00000h, 0BFC66000h-$ ;fill with original data

Sony's TTY strings use ,0Ah as linebreak and ,00h as end of string.

Using the memory in the charset region is okay, as long as your code and tty strings fits into that memory space.

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » October 5th, 2022, 4:24 pm

Everything is built and ready to send to the memory card, but I don't think it's anywhere near as easy as just shoving the data into the JOY_DATA I/O address (1F801040h) like I'd hoped. I am not experienced with low-level I/O and I'm a little lost and wondering if there's a split between sending commands and sending actual save data. So I have a few more questions:

1) Sending 0x81 and 0x21 to start transferring the Game ID would trigger as an invalid command, wouldn't it? Since "transfer aborts immediately after the faulty command byte" wouldn't my Game ID string fail to send anyway? Unless the memory card itself is what determines if a command byte is valid or not.

2) Maybe I should be using higher-level memory card access functions, file load and write, instead? I'm sending known binary data but maybe these functions are the only way (or maybe they're just for writing actual memory blocks instead of simple signaling commands).

3) How do I know that the memory card is initialized at this point in the BIOS? Should I call InitCARD2(pad_enable), StartCARD2(), and _bu_init() just to be safe? Maybe this is also just for when you're writing actual save blocks?

4) Will the slow speed of memory card access affect debugging, or with the TTY output logging JOY commands will the command sent show up immediately, before the system has had to spend time processing it?

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » October 5th, 2022, 10:22 pm

0) There is no difference between sending command bytes and sending data bytes. That said about sending bytes, the README.md is using a different notation: CMND=SendByte, DATA=ReceiveResponseByte.

1) Yes, the memory card determines what it considers as valid. The memcard pro thing should accept the mecard pro commands, a regular memory card (or an empty slot without memory card inserted) won't accept those commands. That is, they won't respond with ACK signals to request the next command byte.

The https://gitlab.com/chriz2600/ps1-game-i ... /README.md mentions a corner case about some PS1D bus sniffer device, I don't know what that device is good for, but if you want to "support that PS1D thing without having a memcard pro inserted" then you would need to ignore missing ACKs and keeping sending the command bytes (after ACK timeouts).

2) The file io functions are useless for sending custom commands. The other memcard related kernel functions don't seem to be useful either.

3) The memcard doesn't require any initialization. The only thing that may need to be initialized are the memcard registers in the console (eg. set the correct baudrate).
The more important part is to make sure that the kernel card/joypad functions won't interfere with your command transfer. I am not sure if that's required (depends on wheter the kernel has pad/card handling enabled at time when sending your command).
You might need to execute kernel StopPad/StardPad before/after your transfer (that might be best).
Other idea would be Enter/ExitCriticalSection (but that might still interfere if it's done during joypad transfer).

4) The slow speed affecting debugging? No, but other way around: Timing emulation may be a bit inaccurate and more flexible as on real hardware. I wouldn't use TTY messages during the command transfer.

Before testing the ID comman on hardware, be sure to test something like the standard Get Memory Card ID Command (81h,53h) in emulation.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 381
Joined: Nov 12, 2012
Contact:

Post by nocash » October 6th, 2022, 9:00 am

This link won't show any information with win9x + retrozilla:
https://gitlab.com/chriz2600/ps1-game-i ... /README.md
This link works on win9x:
https://gitlab.com/chriz2600/ps1-game-i ... /README.md
I've had a closer look at the latter README.md document... and, well, there are confusing errors:

The introduction claims that joypad commands start with "0x42", that mistake doesn't matter for memcard access, but it's a bit like saying "Better don't trust this document!"

The "GameID Send" command has a length byte, which would suggest that the total command length is "4+length". But at closer look, the left column suggests that it does always want 100h bytes (that would imply that the string must be padded with some unspecified values).

Command 20h,22h,23h,25h are said to be 6 bytes long, but command 24h is said to be only 5 bytes long. That might be a firmware design feature, or a typo, or I wouldn't be too surprised if it turns out that they are actually 7 or 8 bytes long.

The most confusing part is this sentence describing the commands "...one reserved byte at the moment, followed by the length of the transmission that follows."

The best explantation is that the sentence is completely meaningless, ie. that it's just saying "followed by further bytes".

Or it might refer to an actual "length byte", that would suggest that "GameID Send" is 4+length bytes long (not fixed length with 100h bytes). But all other commands are described to send a 00h as fourth byte, so they would be only 4+00h bytes long... which would imply that all command descriptions are incorrect.

I could think of three solutions:
- reverse engineering: Count the number of ACKs per command (a command with N bytes should respond with N-1 ACKs).
- try to contact the author
- send something to the memcard and if it's working then it's perhaps close enough to the actual command format

User avatar
bobrocks95
Curious PSXDEV User
Curious PSXDEV User
Posts: 17
Joined: Sep 27, 2022

Post by bobrocks95 » October 6th, 2022, 3:02 pm

nocash wrote: October 5th, 2022, 10:22 pm 0) There is no difference between sending command bytes and sending data bytes. That said about sending bytes, the README.md is using a different notation: CMND=SendByte, DATA=ReceiveResponseByte.

1) Yes, the memory card determines what it considers as valid. The memcard pro thing should accept the mecard pro commands, a regular memory card (or an empty slot without memory card inserted) won't accept those commands. That is, they won't respond with ACK signals to request the next command byte.

The https://gitlab.com/chriz2600/ps1-game-i ... /README.md mentions a corner case about some PS1D bus sniffer device, I don't know what that device is good for, but if you want to "support that PS1D thing without having a memcard pro inserted" then you would need to ignore missing ACKs and keeping sending the command bytes (after ACK timeouts).
Before testing the ID comman on hardware, be sure to test something like the standard Get Memory Card ID Command (81h,53h) in emulation.
Good idea, I've switched to just testing the 81h,53h, status command until I get that working and see JOY activity on the TTY output.

Still a bit lost on sending the commands though. I'm just writing one byte to 0x1F801040 at a time- should I then wait in a loop until JOY_STAT.7=0 (/ACK sent back by the memcard), set JOY_CTRL.4=1 to reset IRQ7, and then I can read the value at 0x1F801040 and send the next byte? Sounds right to me but the documentation wording of "simultaneously, a byte is received" makes it sound like it's instant.

I also maybe need to select the slot with pins 1 and 13 on JOY_CTRL first, with a loop to wait for the delay (docs mention number of cycles to wait for different controllers, maybe it's different for memory cards)?

EDIT: This is going well so far, just need to do some more work on it. I had to set JOY_MODE, JOY_BAUD, and JOY_CTRL first it looks like. Not sure what the JOY_CTRL delay needs to be for the port selection, but I set it at 500 or so cycles if my math's correct. Also mostly writing in assembly now which sucks but I'm much faster than last week with it and at this point it's easier than trying to think in C first.

And for reference the PS1D is the PS1 Digital, which is an HDMI mod for SCPH-550x-700x consoles- it can read the Game ID as well if you have an XStation or UniROM sending the commands out and automatically switch video settings per-game, but like it says, it will not send an /ACK signal back. I'm not too concerned with that at the moment since the slim PSOne doesn't even support the mod. I guess if what I said above is correct for sending commands, I'd instead just wait a safe number of cycles and continue.
2) The file io functions are useless for sending custom commands. The other memcard related kernel functions don't seem to be useful either.
Good to know!
3) The memcard doesn't require any initialization. The only thing that may need to be initialized are the memcard registers in the console (eg. set the correct baudrate).
The more important part is to make sure that the kernel card/joypad functions won't interfere with your command transfer. I am not sure if that's required (depends on wheter the kernel has pad/card handling enabled at time when sending your command).
You might need to execute kernel StopPad/StardPad before/after your transfer (that might be best).
Other idea would be Enter/ExitCriticalSection (but that might still interfere if it's done during joypad transfer).
Calling StopPad2 is fine, trying to call StartPad2 after sending data causes game booting to hang- maybe InitPad2 needs to be called?
4) The slow speed affecting debugging? No, but other way around: Timing emulation may be a bit inaccurate and more flexible as on real hardware. I wouldn't use TTY messages during the command transfer.
TTY output will be off in the end to save on code space and improve timing.
nocash wrote: October 6th, 2022, 9:00 am This link won't show any information with win9x + retrozilla:
https://gitlab.com/chriz2600/ps1-game-i ... /README.md
This link works on win9x:
https://gitlab.com/chriz2600/ps1-game-i ... /README.md
I've had a closer look at the latter README.md document... and, well, there are confusing errors:

The introduction claims that joypad commands start with "0x42", that mistake doesn't matter for memcard access, but it's a bit like saying "Better don't trust this document!"

The "GameID Send" command has a length byte, which would suggest that the total command length is "4+length". But at closer look, the left column suggests that it does always want 100h bytes (that would imply that the string must be padded with some unspecified values).

Command 20h,22h,23h,25h are said to be 6 bytes long, but command 24h is said to be only 5 bytes long. That might be a firmware design feature, or a typo, or I wouldn't be too surprised if it turns out that they are actually 7 or 8 bytes long.

The most confusing part is this sentence describing the commands "...one reserved byte at the moment, followed by the length of the transmission that follows."

The best explantation is that the sentence is completely meaningless, ie. that it's just saying "followed by further bytes".

Or it might refer to an actual "length byte", that would suggest that "GameID Send" is 4+length bytes long (not fixed length with 100h bytes). But all other commands are described to send a 00h as fourth byte, so they would be only 4+00h bytes long... which would imply that all command descriptions are incorrect.

I could think of three solutions:
- reverse engineering: Count the number of ACKs per command (a command with N bytes should respond with N-1 ACKs).
- try to contact the author
- send something to the memcard and if it's working then it's perhaps close enough to the actual command format
Hopefully I can contact one of the people involved easily enough, through Twitter DMs or something. I think the only major concern is if the GameID Send command is 4+length bytes, or always padded out to 100h bytes. The "followed by the length" does sound to me like they just meant "followed by further bytes (per command tables below)", as they thought maybe we should include the reserve bytes in case we can do something with them in the future.

And I wonder where they pulled 0x42 from, it's so specific for a wrong value.

One more thing I'll throw on here at the end since it might actually be important is that I have an instruction

Code: Select all

slti    r9,r9,0x0A
That keeps getting turned into

Code: Select all

jmp     0B4A40028h
And trying to change it back in the debug code section each time I have to use

Code: Select all

setlt    r9,r9,0x0A
Because the assembler will only take slti and the editor will only take setlt (differing names between the .nocash directive and not is fine, the actual problem is it turning into a jmp).

User avatar
MottZilla
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 81
Joined: Jul 04, 2015
Location: North America

Post by MottZilla » October 6th, 2022, 6:43 pm

Good luck getting it working. I was asked by some to see if I could support it in Stealth Unlocker. I'm willing to add support for it but it seemed overly complicated at the time, and not having the real hardware to test with made it pointless to even attempt. Well that and ofcourse no emulator can really test it either.

But I see the appeal in automatically selecting the game's own memory card image for you.

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests