PS1 Emulation

From PS4 Developer wiki
Jump to navigation Jump to search

Description

Playstation 1 emulator called internally ps1hd. Emulation on PS4 is handled differently comparing to PS3. Each PS1 game PS4 package file (.pkg) include emulator itself, so there is no included emulator in PS4 firmware. Fact that emulator is now included in game pkg, is slightly complicating providing compatibility list, as emulators include some per title patches, and different default settings. Next difference is that BIOS/ROM in external file is included in .pkg, emu need different region bios for different region titles. This time bios is not any special version, standard SCPH-550X is used. PS1 Emulator supports LUA scripting by "Lua Bridge", is powerful interface that provide many possibilities to improve compatibility. Memory card is created at first run of emulator, so you don't need to include one in pkg. Emulator have some leftovers from PSP emulator (like axinsnreplace), so core of non PS1 specific functions is the same as in PSP emu. Rest of emu seems to be "inspired" by mednafen.


Configuration Files

config-emu-ps4.txt

Command Values Notes Usage
--wait
--bios path Need to match region of game, relative to sandbox root --bios="BIOS/SCPH5502.bin"
--configpath
--texdump
--texreplace
--region SCEE SCEA SCEI Image/Bios region --region="SCEE"
--image path game image path, sandbox root relative "data/MyGame.bin"
--libcrypt "CRC16" Libcrypt magic, unknown what is really hashed. required for many PAL games, Without it a lot of games will either crash or produce glitches --libcrypt="0xAB34"
--scale 1 , 2 , 4, 6, auto 1 = 1280x720, 2 = 1920x1080, 4 = 3840x2160, auto= same as ps4 video settings(?) please keep in mind that even using scale=1 can cause upscaling glitches scale=2
--antialias off?, SSAA4x , MSAA4x same as above, using this can cause visual glitches on games that scales bad --antialias=SSAA4x
--gpu-scanout-fps-override ntsc, pal? --gpu-scanout-fps-override=ntsc
--remap ? Remap Buttons ? ?
--multitap on,off Enables multitap for games like Crash Bash --multitap=true
--metal-gear-solid 0,1 Specific Command for MGS1 --metal-gear-solid=1
--vram-read-frame-delay True? False? Speedhack?? ?
--sim-analog-pad Enable joysticks to work instead of d-pad? --sim-analog-pad=0x2020
--cdrom-cmd-time 0,100? Can be used to fix black screens --cdrom-cmd-time=100
--cdrom-max-seek true, false Can be used to fix black screens --cdrom-max-seek=true
--texrecent true , false Optimize texture hashes Leading To better Performance --texrecent=true

XXXXYYYYY.LUA


scripts/XXXXYYYYY.LUA
Lua patches are split between 2 categories R3K (r3000 mips), and EM (emulator). Objects do not need to be called in order for their commands to be usable, contrary to the PS2's emulator.

R3000 commands

Command Usage Example Notes
GetPC R3K_GetPC() Return current Program counter.
SetPC R3K_SetPC(address) Set current Program counter to address.
GetHi R3K_GetHi Return Hi register value.
SetHi R3K_SetHi(value) Set Hi register value.
GetLo R3K_GetLo Return Lo register value.
SetLo R3K_SetLo(value) Set Lo register value.
GetGpr R3K_GetGpr(reg) Return register value, require formatting like here: r3k.GetGpr(gpr.a0).
SetGpr R3K_SetGpr(reg, value) Set register value, require formatting like here: r3k.GetGpr(gpr.a0, value).
ReadMem8 R3K_ReadMem8(address) Read/return byte from address.
ReadMem16 R3K_ReadMem16(address) Read/return half from address.
ReadMem32 R3K_ReadMem32(address) Read/return word from address.
ReadMemFloat R3K_ReadMemFloat(address) Read/return float from address.
ReadMemStr R3K_ReadMemStr(address) Read/return string from address.
WriteMem8 R3K_WriteMem8(address, value) Write/set selected memory as byte to value.
WriteMem16 R3K_WriteMem16(address, value) Write/set selected memory as half to value.
WriteMem32 R3K_WriteMem32(address, value) R3K_WriteMem16(0x0006c71c,0x0900) Write/set selected memory as word to value.
WriteMemFloat R3K_WriteMemFloat(address, value) Write/set selected memory as float to value.
WriteMemStr R3K_WriteMemStr(address, value) Write/set selected memory as string to value.
WriteMemStrZ R3K_WriteMemStrZ(address, value)
AddHook R3K_AddHook(address, original opcode, function/hook) Add hook into mips code.
RemoveHook R3K_RemoveHook(?) Remove hook from mips code.
InsnReplace R3K_InsnReplace(address, original opcode, replace opcode) similar to pcsx2 pnach, but additionally use original opcode as a check.
FuncReplace R3K_FuncReplace(address, original opcode, function name) Hook/replace function in mips code with predefinied one.
BurnCycles R3K_BurnCycles()
FlushCache R3K_FlushCache() Flush mips instruction cache.

Emulator commands

Command Usage Example Notes
PadRead EM_PadRead() Return pad state (pushed buttons).
PadReadLeftStick EM_PadReadLeftStick() Return pad left stick state.
PadReadRightStick EM_PadReadRightStick() Return pad right stick state.
PadSetButtonsMode EM_PadSetButtonMode(value) Set some pad mode, in one of official configs described as "switch Select/Start -> Touchpad/Options mode" with used value 2.
AddVsyncHook EM_AddVsyncHook(anything) Add hook that trigger on every vsync, param usually will be previously prepared function.
RemoveVsyncHook EM_RemoveVsyncHook() Remove hook that trigger on every vsync.
ThrottleMax EM_ThrottleMax() Remove framelimiter, used frequently for loadings.
ThrottleNormal EM_ThrottleNormal() Set framelimiter to default game value.
Log EM_Log(value) Print debug messages to usermode console, ex. emu.Log(string.format("Overlay: %02x", overlay)).
GetNativeLanguage EM_GetNativeLanguage() Return used PS4 language.
LoadConfig EM_LoadConfig()
SaveConfig EM_SaveConfig()
LoadState EM_LoadState() Load savestate, seems to be disabled in Medievil emu.
SaveState EM_SaveState() Save savestate, seems to be disabled in Medievil emu.
PostEffect EM_PostEffect()
PostEffectParams EM_PostEffectParams()
NeoMode EM_NeoMode() Return 1 if PS4 PRO, 0 otherwise.
CRC32
AddFBMapping EM_AddFBMapping( , , , ) Add framebffer mapping, in Medievil used with EM_AddFBMapping(768, 256, 180, 256) values.
RemoveFBMapping EM_RemoveFBMapping( , ) Remove framebffer mapping, in Medievil used with EM_RemoveFBMapping(768, 256) values.
Launch EM_Launch("path") Emulator is able to launch selfs in own sandbox, require full path (for example "/app0/folder/my_self.bin"), can be used for multidisc games.


LUA example:

local patcher = function()

R3K_WriteMem16(0x0006c71c,0x0900)
end

EM_AddVsyncHook(patcher)

Emulators

Every emulator is programmed in a different way, sometimes choosing the right emulator is the only possible way to fix a game. Emulators are not provided pre-installed on the ps4, they have to be unpacked from a backup that's downloaded from the ps store from that specific game. this list includes The typical usage of some of The emulators.
Emulator Usage API Version Similar emulators (Usage)
Syphon filter Most popular emulator so far and the one with the highest compatibility, It's used in PSXFPKG v0.3 as the default emulator ? ?
Medievil An unofficial emulator made by sony that's very bad emulator in terms of compatibility. ? ?

PAL Libcrypt games

Some PAL PSX games include libcrypt protection, those are known to cause issues for emulators.

List

  • Actua Ice Hockey 2 (Europe)
  • Anstoss - Premier Manager (Germany)
  • Ape Escape (Europe) , (France) , (Germany) , (Italy)
  • Ape Escape - La Invasion de los Monos (Spain)
  • Asterix - Mega Madness (Europe) (En,Fr,De,Es,It,Nl)
  • Barbie - Aventure Equestre (France)
  • Barbie - Race & Ride (Europe) , (Germany) , (Italy) , (Spain)
  • Barbie - Sports Extreme (France)
  • Barbie - Super Sports (Germany) , (Europe) , (Italy) , (Spain)
  • BDFL Manager 2001 (Germany)
  • BDFL Manager 2002 (Germany)
  • Canal+ Premier Manager (Europe) (Fr,Es,It)
  • Crash Bash (Europe) (En,Fr,De,Es,It)
  • CTR - Crash Team Racing (Europe) (En,Fr,De,Es,It,Nl) (EDC)
  • CTR - Crash Team Racing (Europe) (En,Fr,De,Es,It,Nl) (No EDC)
  • Dino Crisis (Europe) , (France) , (Germany) , (Italy) , (Spain)
  • Disney Fais Ton Histoire! - Mulan (France)
  • Disney Libro Animato Creativo - Mulan (Italy)
  • Disney's Tarzan (Europe) , (Netherlands) , (Sweden) , (Germany) , (Italy) , (France) , (Spain)
  • Disney's 102 Dalmatians - Puppies to the Rescue (Europe) (Fr,De,Es,It,Nl)
  • Disney's 102 Dalmatians - Puppies to the Rescue (Europe)
  • Disney's Aventura Interactiva - Mulan (Spain)
  • Disney's Story Studio - Mulan (Europe)
  • Disney's Verhalenstudio - Mulan (Netherlands)
  • Disneys Interaktive Abenteuer - Mulan (Germany)
  • EA Sports Superbike 2000 (Europe) (En,Fr,De,Es,It,Sv)
  • Eagle One - Harrier Attack (Europe) (En,Fr,De,Es,It)
  • Esto es Futbol (Spain)
  • F.A. Premier League Football Manager 2001, The (Europe)
  • F1 2000 (Europe) (En,Fr,De,Nl)
  • F1 2000 (Italy)
  • Final Fantasy IX (Europe) , (France) , (Germany) , (Italy) , (Spain) , (Disc 1)
  • Final Fantasy IX (Europe) , (France) , (Germany) , (Italy) , (Spain) , (Disc 2)
  • Final Fantasy IX (Europe) , (France) , (Germany) , (Italy) , (Spain) , (Disc 3)
  • Final Fantasy IX (Europe) , (France) , (Germany) , (Italy) , (Spain) , (Disc 4)
  • Final Fantasy VIII (Europe, Australia) , (France) , (Germany) , (Italy) , (Spain) , (Disc 1)
  • Final Fantasy VIII (Europe, Australia) , (France) , (Germany) , (Italy) , (Spain) , (Disc 2)
  • Final Fantasy VIII (Europe, Australia) , (France) , (Germany) , (Italy) , (Spain) , (Disc 3)
  • Final Fantasy VIII (Europe, Australia) , (France) , (Germany) , (Italy) , (Spain) , (Disc 4)
  • Football Manager Campionato 2001 (Italy)
  • Formula One 99 (Europe) (En,Es,Fi)
  • Formula One 99 (Europe) (En,Fr,De,It)
  • Frontschweine (Germany)
  • Fussball Live (Germany)
  • Fussball Manager 2001 (Germany)
  • Galerians (Europe) , (France) , (Germany) , (Disc 1)
  • Galerians (Europe) , (France) , (Germany) , (Disc 2)
  • Galerians (Europe) , (France) , (Germany) , (Disc 3)
  • Gekido - Urban Fighters (Europe) (En,Fr,De,Es,It)
  • Hogs of War (Europe)
  • Italian Job, The (Europe) , (Germany)
  • Jackie Chan Stuntmaster (Europe)
  • Le Mans 24 Hours (Europe) (En,Fr,De,Es,It,Pt)
  • Legacy of Kain - Soul Reaver (Europe) , (France) , (Germany) , (Italy) , (Spain)
  • Les Cochons de Guerre (France)
  • LMA Manager 2001 (Europe)
  • LMA Manager 2002 (Europe)
  • Lucky Luke - Western Fever (Europe) (En,Fr,De,Es,It,Nl)
  • MediEvil (Europe) , (France) , (Germany) , (Italy) , (Spain)
  • MediEvil 2 (Europe) (En,Fr,De)
  • MediEvil 2 (Europe) (Es,It,Pt)
  • MediEvil 2 (Russia)
  • Men in Black - The Series - Crashdown (Europe) , (France) , (Germany) , (Italy) , (Spain)
  • Michelin Rally Masters - Race of Champions (Europe) (En,De,Sv)
  • Michelin Rally Masters - Race of Champions (Europe) (Fr,Es,It)
  • Mike Tyson Boxing (Europe) (En,Fr,De,Es,It)
  • Mission - Impossible (Europe) (En,Fr,De,Es,It)
  • MoHo (Europe) (En,Fr,De,Es,It)
  • Monde des Bleus, Le - Le jeu officiel de l'equipe de France (France)
  • N-Gen Racing (Europe) (En,Fr,De,Es,It)
  • Need for Speed - Porsche 2000 (Europe) (En,De,Sv)
  • Need for Speed - Porsche 2000 (Europe) (Fr,Es,It)
  • Parasite Eve II (Europe) , (France) , (Germany) , (Italy) , (Spain) , (Disc 1)
  • Parasite Eve II (Europe) , (France) , (Germany) , (Italy) , (Spain) , (Disc 2)
  • PGA European Tour Golf (Europe) (En,De)
  • Premier Manager 2000 (Europe)
  • Prince Naseem Boxing (Europe) (En,Fr,De,Es,It)
  • Radikal Bikers (Europe) (En,Fr,De,Es,It)
  • RC Revenge (Europe) (En,Fr,De,Es)
  • Resident Evil 3 - Nemesis (Europe) , (France) , (Germany) , (Ireland) , (Italy) , (Spain)
  • Ronaldo V-Football (Europe) (De,Es,It,Pt)
  • Ronaldo V-Football (Europe) (En,Fr,Nl,Sv)
  • SaGa Frontier 2 (Europe) , (France) , (Germany)
  • SnoCross Championship Racing (Europe) (En,Fr,De,Es,It)
  • Space Debris (Europe) , (France) , (Germany) , (Italy)
  • Speed Freaks (Europe)
  • Spyro - Year of the Dragon (Europe) (En,Fr,De,Es,It) (v1.0) , (v1.1)
  • Spyro 2 - Gateway to Glimmer (Europe) (En,Fr,De,Es,It)
  • Sydney 2000 (Europe) , (France) , (Germany) , (Spain)
  • TechnoMage - De Terugkeer der Eeuwigheid (Netherlands)
  • TechnoMage - Die Rueckkehr der Ewigkeit (Germany)
  • TechnoMage - En Quete de L'Eternite (France)
  • TechnoMage - Return of Eternity (Europe)
  • Theme Park World (Europe) (En,Fr,De,Es,It,Nl,Sv)
  • This Is Football (Europe) (Fr,Nl)
  • This Is Football (Europe) , (Italy)
  • TOCA World Touring Cars (Europe) (En,Fr,De)
  • TOCA World Touring Cars (Europe) (Es,It)
  • UEFA Euro 2000 (Europe) , (France) , (Germany) , (Italy)
  • UEFA Striker (Europe) (En,Fr,De,Es,It,Nl)
  • Urban Chaos (Europe) (En,Es,It)
  • Urban Chaos (Germany)
  • V-Rally - Championship Edition 2 (Europe) (En,Fr,De)
  • Vagrant Story (Europe) , (France) , (Germany)
  • Walt Disney World Quest - Magical Racing Tour (Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da)
  • Wonderworld 2: Arena Of Courage (Europe) (En,Es,Fr,De,It,Da)
  • Wip3out (Europe) (En,Fr,De,Es,It)

Known Issues

The exact effects of libcrypt depend on the game. However, they usually render the game unplayable in some form. Here is list of libcrypt-caused issues known to the community. Be sure to patch these games before creating a pkg, or try to fix them by using the --libcrypt command in the emu config.

Game Behavior
Ape Escape (PAL)

Main menu navigation will be completely disabled, making you unable to start the game.

Crash Team Racing (PAL)

Game will hang at the end of the loading screen, when trying to use a warp from the main level to any race track.

Final Fantasy VIII (PAL)

Game immediately hangs on a black screen. It doesn't even play any intros.

Legacy of Kain: Soul Reaver (PAL)

The game will hang when you're introduced with the combat tutorial when the camera pans to show the enemies.

Lucky Luke: Western Fever (PAL)

The game stops when you get to the Mexican guy blocking the bridge, he just won't move from there, ever. Even when you complete the quest. The game also has anti-cracking protection where the game will block a path with a fallen tree + maybe more.

MediEvil (PAL)

Will have a disc error icon upon loading The Hilltop Mausoleum. Interesting to note this was actually the FIRST game to use LibCrypt.

MediEvil 2 (PAL)

Will also have the same disc error icon as above, except upon loading Kensington.

PGA European Tour Golf (PAL)

In the third hole of the first tournament or by selecting some holes, the game will get stuck in "demo" mode (and will not you play anything).

Resident Evil 3: Nemesis (PAL)

Will hang at the "Game contains violence and gore" screen.

Spyro 3: Year of the Dragon (PAL)

Interesting case for this one, the game will eventually randomly delete eggs, reset progress with unlocked characters, remove sheep in boss battles, change the language and even tell you off for playing a "hacked copy" + more. Interesting to note that the game also detected early LibCrypt knockout PPF patches back when the game was first released as it had checksum checks throughout the game, which caused the same effects above. The US platinum release only has anti mod detection (not libcrypt) and will do the above effects if it realises it's been modified. The original US release appears to not have any protection.

This is Football (PAL)

Hangs on the loading screen going ingame.

V-Rally: Championship Edition 2 (PAL)

The game will endlessly load on the heartbeat loading screen (with no disc activity).

Vagrant Story (PAL)

Will hang on the "now loading"-screen, after choosing "new game" on the main menu.

Wonderworld 2: Arena Of Courage (PAL)

Still hangs on the "Loading, please wait..."-screen, when you start the mission.

Wip3out (PAL)

The game will freeze when passing the finish line.

Multi-Disc support

This needs more testing but in theory it should work as follows.

On Real PS1 Hardware, PS2, PSP, PSV, PS3

Example Game: Final Fantasy VII containing 3 Discs:

  • Before the Game asks you to change Discs, it will ask you if you wish to save the Game.
    • If doing so, the Save File already creates a "Flag" containing Information that this Save File requires the next Disc (this is perfectly visible with Final Fantasy VIII as seen here).
      • Example: When Aerith dies and you fight JENOVA, the Game creates the Save File asking for CD 2 while you are still on CD 1.
  • After you saved the Game, it will immediately ask you to insert the next Disc.
    • The reason why this works and it's supported because in theory, you could save your Game right before you get asked to change the Disc but instead of doing so, you shut down your console and decides to play further tomorrow.
      • So when loading the same Save File on next day, it will already ask in the beginning for the next Disc.
        • If the next Disc is already inserted, then it will load the Game immediately.
        • If not then it will ask again for switching Discs (same when inserting a wrong Disc like "Disc 3" for instance but "Disc 2" is needed).

So how to do this on a PS4?

Since as mentioned above the problematic we have is that every PKG contains not only the Game as an Image-File, but also the Emulator and a Save File itself. So a workaround is needed:

  • You create a FPKG containing Disc 1 of Final Fantasy VII only (Example Content ID = CUSAFF7D1).
  • You play the Game normally until it asks you to save the Game before it will ask you to change the Disc.
  • Save the Game and close the Application.
  • On your PS4 Harddrive, there should be theoretically the Save File somewhere (within the Game Files from the Game itself ???).
  • Dump the Save File and edit the "Parameters" (PARAM.SFO ???) so CUSAFF7D1 gets into CUSAFF7D2.
  • Create your next FPKG containing Disc 2 of Final Fantasy VII only and insert your edited Save File (Content ID = CUSAFF7D2 for both the FPKG as the Save File).
  • Start the new FPKG created and it should recognize your Save File and load the Game from the beginning of Disc 2
  • Do the same process for every other additional Disc.

Alternative solution - Disc Merge

Alternatively ps1 discs can be merged into single bin/cue. There could be potential limitations in file size because MM:SS:FF can only go up to 99:99:99 which translates to around 870MB. For sure this will be problem for games with CDDA tracks. For now there is no confirmation that this limit apply to data only games. How hard is disc merging depends highly on game we want to use. Parasite Eve is one of easiest games to do that since second disc check is triggered only if files from disc 2 are not present on current disc, which they are since discs are merged. Game also use the same EXE and PE file on both discs, and do not use lba based tables. So merging discs is literally repacking them into single disc. But different games use different approaches, games like MGS need additional patches to few files to skip shell open checks, and lba adjustments. For now Chinese Parasite Eve fan translation is only confirmed game that works (thx 苏宇 for playing whole game to test it).

Memory mapping

Offset From Offset To Name Memory Name (PS4)
0x200000000 0x208000000 R3000 Memory HeapDirectMem[0]

Converting psx cheats for the ps4

Psx cheats into a shn

Only tested in Syphon filter's emulator

1. Get an offset    [You can get them from Gamehacking.org / Duckstation / Epsxe]

2. Remove the first 2 numbers from the offset

3. Increase the offset by 0xEB2A0 using a hex calculator and add it to your shn

For ps4cheater

Only tested in Syphon filter's emulator

1. Get an offset    [You can get them from Gamehacking.org / Duckstation / Epsxe]

2. Remove the first 2 numbers from the offset

3. Increase the offset by 0x2000EB2A0 using a hex calculator and use it in ps4 cheater

PC register script (Syphon Filter 1)


For the usage in PS4cheater.
PSX.cht

1.5|eboot.bin|ID:|VER:|FM:505
simple pointer|pointer|4 bytes|@A3A2B0_2_3A2B0+C4|data|4 bytes|2147848120|0|PC|

PC register script (Syphon Filter 3)

1.5|eboot.bin|ID:|VER:01.00|FM:505
simple pointer|pointer|4 bytes|@A51220_2_51220+C4|data|4 bytes|2147752604|0|RA|
simple pointer|pointer|4 bytes|@A51220_2_51220+D4|data|4 bytes|2147825396|0|PC|

TOC file layout

For multi bin images, probably require emu from ps plus.
Track entry structure:

Entry Nº Offset Length Name Example Notes
1 0x00 0x01 (1 byte) TYPE 0x41/0x01 entry flags
0x01 0x01 (1 byte) TNO 00 Track number, usually 00, bcd
0x02 0x01 (1 byte) POINT 0xA0/0xA1/0xA2/0x01/0x02/0x03/etc bcd + special case A0-A2.
0x03 0x01 (1 byte) MIN varies absolute, bcd
0x04 0x01 (1 byte) SEC varies absolute, bcd
0x05 0x01 (1 byte) FRAME varies absolute, bcd
0x06 0x01 (1 byte) ZERO 00 always zero
0x07 0x01 (1 byte) PMIN varies bcd
0x08 0x01 (1 byte) PSEC varies bcd
0x09 0x01 (1 byte) PFRAME varies bcd
Up to 102 same structure than the previous entry

POINT indicates successive track numbers, and PMIN, PSEC and PFRAME indicate the starting time of that track.
POINT = A0, PMIN gives the physical track number of the first piece of data (PSEC and PFRAME are zero).
POINT = A1, PMIN indicates the last track on the disc
POINT = A2, the starting point of the lead-out track is given in PMIN, PSEC and PFRAME.
POINT = 01 - 99 Index number within track.
POINT = 00, Pause (2sec?, Also pregap?)

Folder/File layout

Example: Medievil internal emulator, standalone pkg can differ.

├──bios
│   ├── scph5500.bin
│   ├── scph5501.bin
│   └── scph5502.bin
├──config-emu-ps4.txt
├──data
│   └── image.bin
├──eboot.bin
├──sce_module
│   ├── libc.prx
│   ├── libSceAudioLatencyEstimation.prx
│   ├── libSceFace.prx
│   ├── libSceFaceTracker.prx
│   ├── libSceFios2.prx
│   ├── libSceHand.prx
│   ├── libSceHandTracker.prx
│   ├── libSceHeadTracker.prx
│   ├── libSceJobManager.prx
│   ├── libSceNpToolkit2.prx
│   └── libSceS3DConversion.prx
├──sce_sys
│   └── param.sfo
├──scripts
│   └── XXXXYYYYY.lua

Emulator patches

Syphon Filter 3 emu

Emu build from 2023-Feb-17

Remove dithering

Universal dithering removal patch, works with every single game. PS1 cheats/patches are no longer required to disable dither pattern. To apply unself self file, edit, and sign it again after that. Alternatively you can use cheat engine, offset need to be adjusted to emu base then.
Replaces *and ecx, 7FFh* with *and ecx, 5FFh* to always remove dither enable bit on E1 write.

  • Emu memory offset: 0x50EA2
  • Elf memory offset: 0x54EA2

Original bytes:

81 E1 FF 07 00 00

Replace to:

81 E1 FF 05 00 00

Links