Saturday, December 22, 2018

Modding my PS1 - Memory card backup (PSX-VX Part 0)

I recently found my old PS1 memory cards and wondered how to retrieve the data on a computer.
This is the first article of a series on the original Playstation.
[Source code can be found here: https://github.com/electrojack/psxvx]

Step 1: Understanding the hardware
A memory card has 8 connections, all of them are linked to the corresponding ones of the controller in the same port.



(Data = grey, Command = purple, etc)

So there is VCC, GND, +7V (vibration).
The Acknowledge port is for the device to send an acknowledgement command after having received a byte.
Then Data (MISO), Command (MOSI), Attention (CS) and Clock (SCK) are standard SPI.

The rest of the info can be read there: https://problemkaputt.de/psx-spx.htm#controllerandmemorycardioports


Step 2: Software
As you can read in the PS1 Bible, talking to the memory card is pretty trivial.
Even better: Shendo created a program to flash to an AVR that talks to memory cards and a Python script that talks to this program.
That's what I used.

I adapted the .ino (C file to use with the Arduino software) program for the ATmega8535 I used for this task.
I also changed the Python script to better take errors into account.
I'll publish these in my PS1 software repo but in the mean time the Shendo's files works perfectly.

Step 3: Making it
I removed the controller/memcard block from the PS1 and soldered wires as in the first image.
MISO, MOSI, CS and SCK were connected to the ATmega8535 as expected, ATT is optional and was left alone and finally it looks like the +7V port can be connected to +3.3V without posing any problems (both with Sony memcards and third party memcards).
I used a Raspberry Pi to control the AVR chip (through RX/TX) but any UART computer would work.

And finally it's quite easy to make it work using the serial port to the chip.

$ python memcarduino.py  -p /dev/serial0 -r memcard.mcr                 
running mcduino check                                                   
passed mcduino check                                                    
Running mcr header check MCDINO                                         
Sending... \xa20001                                                     
Reading 129bytes...                                                     
passed header check                                                     
reading data from memory card...                                        
                                                                        
OK at frame 1/1024  Address:00 00 TimeTaken:0:00:00.225765              
OK at frame 2/1024  Address:00 01 TimeTaken:0:00:00.225847              
OK at frame 3/1024  Address:00 02 TimeTaken:0:00:00.225859              
...                                                                     
OK at frame 1024/1024 Address: 03 FF TimeTaken:0:00:00.225482           
SUCCESS                                                                 

Then you can use your *.mcr files as virtual memory cards in emulators and store them where you want.










Modding my PS1 - Chipping (PSX-VX Part I)

WHAT
[All the source code can be found here: https://github.com/electrojack/psxvx]
I recently decided to mod a PS1.
After a lot of research I found that the info about chipping was not easily understandable.
The reason is that there are many PS1 motherboards, several different modchips and scarce precise how-tos.

The different PS1 boards are here: https://en.wikipedia.org/wiki/PlayStation_models#Comparison_of_models
The one I bought is a PU-18.

Nearly everybody use PIC modchips but I have ATtiny chips so I used one: a ATtiny13 that was laying around.

If you read that you should know about the protection used in the PS1. If not, read this: https://twitter.com/foone/status/974277587764523010

Now the problem is: where and how should I inject the "SCEE" string?


WHERE
The SCEE string should replace the one actually read on the disk.
This string is sent on a Data line that is accessible on the back of the motherboard.
Also the actual output must be muted so that we can send the SCEE string without it being messed with with the actual data.
Fortunately this muting can be done by putting low a single accessible signal: the so-called Gate pin.


This image shows the back of a PU-18. (bottom left in this picture: http://wiki.psxdev.ru/images/c/ca/PU-18%28b%29.jpg)
On this picture (1) is VCC, (8) is GND, (6) is DATA and (5) is GATE.

HOW
Now that we know the pin (DATA = 6) to monitor, I used my logic analyzer to see the signal I'll have to reproduce.
So I put a legit game CD in the PS1, put my D3 channel on the DATA pin and logged the signal.


And here it is, we can see the "SCEE" string.
This is UART, 250 bits/s, LSB-first.
This info is (fortunately) the same than what we can read here: https://problemkaputt.de/psx-spx.htm#cdromprotectionmodchips

CHIP FIRMWARE
With this info I made the following software and uploaded it on my ATtiny13 (fuses: H:FF, L:6A).
You can find it here: https://github.com/electrojack/psxvx/tree/master/part1_chipping

#define SETOUTPUT(ddr, n) ddr |= _BV(n);
#define SETINPUT(ddr, n) ddr &= ~_BV(n);
#define SETHIGH(port, n) port |= _BV(n);
#define SETLOW(port, n) port &= ~_BV(n);
#include <avr/io.h>
#include <util/delay.h>
#define gate 3
#define data 4
#define bitdur 4
#define pause 72
char scee[4] = "SCEE";
void wb(){_delay_ms(bitdur);}
void uart_start(){SETHIGH(PORTB, data);wb();}
void uart_stop(){SETLOW(PORTB, data);wb();}
void inject_scee(){
    for(int i=0;i<4;i++){
        uart_start();
        for(int j=0;j<8;j++){
            char val = ((scee[i] & (1<<j)) == 0);
            if(val){
                SETHIGH(PORTB, data);
            }else{
                SETLOW(PORTB, data);
            }
            wb();
        }
        uart_stop();
        uart_stop();
    }
    _delay_ms(pause);
}
int main(){
    OSCCAL = 69;
    SETOUTPUT(DDRB, data);
    SETOUTPUT(DDRB, gate);
    while(1){
        inject_scee();
    }
}

After analyzing the output, it's really close to the expected signal.


DOES THIS WORK?
Well...
The PS1 still reads genuine disks so I didn't kill it.
Also I guess that means that the data I inject is recognized as valid.

Booting burned disks is another story as none managed to boot.
I should state that my burned disks are pretty damaged though.



I have no CD burner so I can't test much further.
Although I think it's more or less working for two reasons:
  • all the burned disks I tried manage to go to the Playstation screen
  • one burned CD (Grand Theft Auto) it managed to go to the anti-piracy screen

Still, something must be off because the GTA disk plays normally on another PS1.


WHAT NOW
Two things:
 - fix this to make it actually boot games
 - check whether this chip passes the anti-modchip games (like FFVIII)


EDIT 1:
I tried to clean the lens and changed some timings (I've yet to update the code).
Now GTA sometimes manages to boot, but even then the intro lags a lot.
No other burned CDs boot after the Playstation splash screen.
I have to test a clean burned CD.

EDIT 2:
I moved the laser pot a bit, around 1/16 turn (I don't have any oscilloscope laying around right now), and it now loads both GTA and Vigilante 8 nearly as easily as on the other PS1 I was able to try.
The other games are officially dead according to that PS1.
I still have to perfectly adjust the pot with a scope and finely adjust the timings of the chip software and I guess it would then work flawlessly.

Also, my chip relies on its internal oscillator, which means that its timings may be off because it needs calibration (through the OSCCAL register) and the temperature of the chip affects it.
The correct way to fix this is to use an external oscillator, from the PS1 for exemple.

CONCLUSION
Success!
The PS1 is chipped and boots burned disks.
That was all I wanted so I won't spend more time on this but in order to cleanly finish this work I still have to precisely set the laser pot and fix the oscillator problem.

Sunday, December 2, 2018

Identifying Arduino Pro Mini 5V vs 3.3V

http://electronicsideasforyou.blogspot.com/2017/01/arduino-pro-mini-identifying-voltage.html


RegulatorVoltage
KB333.3
S20K3.3
F34V3.3
L0RA3.3
L0RB3.3
LG333.3
9B273.3
662K3.3
KBAA3.3/5 Selectable
KB505
L055
L0UA5
L0UB5
S8PE5
LG505