One of the most celebrated games of this console generation, Bloodborne saw From Software team up with Sony to produce an epic gothic adventure – rich in lore, deep in gameplay, brutally hard in execution. From a Digital Foundry perspective, its only negative points are technical in nature. Bloodborne’s 30fps frame-rate is poorly implemented, while the potential for 60fps gaming via a PlayStation 4 Pro patch never happened. With that in mind, it was with much interest that we followed the work of Lance McDonald, who chronicled his attempts to hack the Bloodborne code on debug hardware in order to run it at full frame-rate. Footage released shows McDonald getting extremely close to the target – but what is the full story?
Before we go on, it’s worth stressing that the Bloodborne 60fps patch doesn’t work on retail PlayStation 4 consoles and prospective users would need access to hacked or development hardware to experience it, if it were publicly available – which it isn’t. Our interest is in dissecting the game, to see how it works and how effective an official patch could be. To that end, I spoke at length with Lance McDonald over the last week, getting to understand how this hack was achieved, then working with him to test various resolution and performance modes to get a more detailed view on how the From Software engine works and whether Bloodborne – and by extension other Souls titles from the same developer – could run at 60fps instead of its default 30fps. And even if a locked 60fps isn’t possible, we also had to wonder – can the Souls family of titles’ 30fps implementation be hacked to actually work… correctly?
Understanding why this is a problem is key. In an ideal world, games designed for living room displays would all run at 60 frames per second – one new frame for every refresh of the screen, the smoothest possible output, the lowest possible latency. However, the amount of rendering time required for modern game engines often makes this unreasonable, so games can spend twice as much time – two display refreshes – to generate a new frame. It’s 30 frames per second rather than 60, 33.3ms instead of 16.7ms, but because there’s still a consistent persistence for each frame, it still looks smooth.