Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into fuckit
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasnoble committed Mar 11, 2024
2 parents 6b43700 + b77eed3 commit 32e74e5
Show file tree
Hide file tree
Showing 31 changed files with 397 additions and 268 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/macos-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ jobs:
- uses: n1hility/cancel-previous-runs@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Update brew
run: |
brew update --preinstall
- name: Install dependencies
run: ./.github/scripts/install-brew-dependencies.sh
- name: Fetch submodules
Expand Down
270 changes: 124 additions & 146 deletions src/core/psxmem.cc

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/core/psxmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,19 @@ class Memory {

IO<MemoryAsFile> getMemoryAsFile() { return m_memoryAsFile; }

bool isiCacheEnabled() { return m_BIU == 0x1e988; }

private:
friend class MemoryAsFile;
IO<MemoryAsFile> m_memoryAsFile;

int m_writeok = 1;
uint32_t m_biosCRC = 0;

// Shared memory wrappers, pointers below point to these where appropriate
SharedMem m_wramShared;

uint32_t m_BIU = 0;

// hopefully this should become private eventually, with only certain classes having direct access.
public:
uint8_t *m_wram = nullptr; // Kernel & User Memory (8 Meg)
Expand Down
37 changes: 31 additions & 6 deletions src/gui/gui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,10 @@ static void drop_callback(GLFWwindow* window, int count, const char** paths) {

void LoadImguiBindings(lua_State* lState);

ImFont* PCSX::GUI::loadFont(const PCSX::u8string& name, int size, ImGuiIO& io, const ImWchar* ranges, bool combine) {
ImFont* PCSX::GUI::loadFont(const PCSX::u8string& name, int size, ImGuiIO& io, const ImWchar* ranges, bool combine,
bool isBaseFont) {
if (!ranges) ranges = io.Fonts->GetGlyphRangesDefault();

const System::Range knownRange = System::Range(reinterpret_cast<uintptr_t>(ranges));
if (knownRange == System::Range::KOREAN) ranges = io.Fonts->GetGlyphRangesKorean();
if (knownRange == System::Range::JAPANESE) ranges = io.Fonts->GetGlyphRangesJapanese();
Expand All @@ -180,6 +183,28 @@ ImFont* PCSX::GUI::loadFont(const PCSX::u8string& name, int size, ImGuiIO& io, c
if (knownRange == System::Range::THAI) ranges = io.Fonts->GetGlyphRangesThai();
if (knownRange == System::Range::VIETNAMESE) ranges = io.Fonts->GetGlyphRangesVietnamese();

static std::vector<ImWchar> rangesVector;

if (isBaseFont) {
for (unsigned i = 0; ranges[i] != 0; i++) {
rangesVector.push_back(ranges[i]);
}

rangesVector.push_back(0x2190); // ←: U+2190 ↑: U+2191
rangesVector.push_back(0x2193); // →: U+2192 ↓: U+2193
rangesVector.push_back(0x25b3); // △: U+25B3
rangesVector.push_back(0x25b3);
rangesVector.push_back(0x25ef); // ◯: U+25EF
rangesVector.push_back(0x25ef);
rangesVector.push_back(0x2610); // ☐: U+2610
rangesVector.push_back(0x2610);
rangesVector.push_back(0x2715); // ✕: U+2715
rangesVector.push_back(0x2715);

rangesVector.push_back(0);
ranges = rangesVector.data();
}

decltype(s_imguiUserErrorFunctor) backup = [](const char*) {};
std::swap(backup, s_imguiUserErrorFunctor);
ImFontConfig cfg;
Expand Down Expand Up @@ -852,15 +877,15 @@ void PCSX::GUI::startFrame() {
io.Fonts->AddFontDefault();
for (auto& scale : scales) {
m_mainFonts[scale] = loadFont(MAKEU8("NotoSans-Regular.ttf"), settings.get<MainFontSize>().value * scale,
io, g_system->getLocaleRanges());
io, g_system->getLocaleRanges(), false, true);
for (auto e : g_system->getLocaleExtra()) {
loadFont(e.first, settings.get<MainFontSize>().value * scale, io, e.second, true);
loadFont(e.first, settings.get<MainFontSize>().value * scale, io, e.second, true, false);
}
// try loading the japanese font for memory card manager
m_hasJapanese = loadFont(MAKEU8("NotoSansCJKjp-Regular.otf"), settings.get<MainFontSize>().value * scale,
io, reinterpret_cast<const ImWchar*>(PCSX::System::Range::JAPANESE), true);
m_monoFonts[scale] =
loadFont(MAKEU8("NotoMono-Regular.ttf"), settings.get<MonoFontSize>().value * scale, io, nullptr);
io, reinterpret_cast<const ImWchar*>(PCSX::System::Range::JAPANESE), true, false);
m_monoFonts[scale] = loadFont(MAKEU8("NotoMono-Regular.ttf"), settings.get<MonoFontSize>().value * scale,
io, nullptr, false, false);
}
io.Fonts->Build();
io.FontDefault = m_mainFonts.begin()->second;
Expand Down
3 changes: 2 additions & 1 deletion src/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ class GUI final : public UI {
bool m_hasJapanese = false;
float m_currentScale = 1.0f;

ImFont *loadFont(const PCSX::u8string &name, int size, ImGuiIO &io, const ImWchar *ranges, bool combine = false);
ImFont *loadFont(const PCSX::u8string &name, int size, ImGuiIO &io, const ImWchar *ranges, bool combine,
bool isBaseFont);

bool m_reloadFonts = true;
Widgets::ShaderEditor m_outputShaderEditor = {"output"};
Expand Down
98 changes: 98 additions & 0 deletions src/mips/common/hardware/flushcache.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
MIT License
Copyright (c) 2024 PCSX-Redux authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

.include "common/hardware/hwregs.inc"

/* This version of the cache flush routine is designed to be used from
the main ram, and is completely position-independent. This is inspired
from a main-ram version of FlushCache found in the PAL game TOCA World
Touring Cars, SLES-02572. The order of operations is important: the
BIU_CONFIG register has to be modified *after* changing cop0 Status.
Note that normally, nops are required after mutating cop0 Status or
BIU_CONFIG, but since we are running from uncached ram, the pipeline
stalls caused by accessing the SDRAM are enough. */

.section .text.flushCache, "ax", @progbits
.align 2
.set noreorder
.global flushCache
.type flushCache, @function

flushCache:
/* Saves $ra to $t6, and the current cop0 Status register to $t0, and ensure we
are running from uncached ram. */
li $t1, 0xa0000000
move $t6, $ra
bal 1f
mfc0 $t0, $12
1:
or $t1, $ra, $t1
addiu $t1, 4 * 4 /* Jumps to the next instruction after the delay slot. */
jr $t1

/* First, disables interrupts. */
mtc0 $0, $12

/* Writes 0x0001e90c to the BIU_CONFIG register at 0xfffe0130.
This will let us continue to run from uncached memory, while
allowing us to access the i-cache. We keep the constant in
$t2, so we can reuse it later when re-enabling the i-cache. */
li $t5, BIU_CONFIG
li $t2, 0x0001e90c
sw $t2, 0($t5)

/* Isolates the cache, and disables interrupts. */
li $t1, 0x10000
mtc0 $t1, $12

/* Clears only the relevant parts of the i-cache. */
li $t3, 0
li $t4, 0x0f80

1:
sw $0, 0x00($t3)
sw $0, 0x10($t3)
sw $0, 0x20($t3)
sw $0, 0x30($t3)
sw $0, 0x40($t3)
sw $0, 0x50($t3)
sw $0, 0x60($t3)
sw $0, 0x70($t3)
bne $t3, $t4, 1b
addiu $t3, 0x80

/* First, un-isolate the cache. */
mtc0 $0, $12
/* Then, restore the BIU_CONFIG register to 0x0001e988. */
addiu $t2, 0x7c
sw $t2, 0($t5)
/* Finally, restore the cop0 Status register, and return. It
might be unwise to do the mtc0 in the jr delay slot, in
case we arrive back at a cop2 instruction, but further
testing could be useful. */
mtc0 $t0, $12
jr $t6
nop
2 changes: 1 addition & 1 deletion src/mips/openbios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ The ghidra database for it is currently being hosted on a server, alongside a fe

## Commentary

The retail PlayStation BIOS code is a constellation of bugs and bad design. It is very obvious the code has been written hastily, likely by different teams having little to no communication with each other, under heavy time pressure. The fact that the retail console boots at all is nothing short of a miracle. Half of the provided libc in the A0 table is buggy. The BIOS code is barely able to initialize the CD-Rom, and read the game's binary off of it to boot it; anything beyond that will be crippled with bugs. And this only is viable if you respect a very strict method to create your CD-Rom. The memory card and gamepad code is a steaming-hot heap of human excrement. The provided GPU stubs are inefficient at best. The only sane thing that any software running on the PlayStation ought to do is to immediately disable interrupts, grab the function pointer located at 0x00000310 for `FlushCache`, in order put it inside a wrapper that disables interrupts before calling it, and then trash the whole memory to install its own code. The only reason `FlushCache` is required from the retail code is because since the function will unplug the main memory bus off the CPU in order to work, it HAS to run from the 0xbfc0 memory map, which will still be connected. Anything else from the retail code is virtually useless, and shouldn't be relied upon. That being said, doing so will prevent tools from functioning properly, like cheat software, unirom, or even emulators that are sniffing the kernel to do debugging and reporting.
The retail PlayStation BIOS code is a constellation of bugs and bad design. It is very obvious the code has been written hastily, likely by different teams having little to no communication with each other, under heavy time pressure. The fact that the retail console boots at all is nothing short of a miracle. Half of the provided libc in the A0 table is buggy. The BIOS code is barely able to initialize the CD-Rom, and read the game's binary off of it to boot it; anything beyond that will be crippled with bugs. And this only is viable if you respect a very strict method to create your CD-Rom. The memory card and gamepad code is a steaming-hot heap of human excrement. The provided GPU stubs are inefficient at best. The only sane thing that any software running on the PlayStation ought to do is to immediately disable interrupts, and then trash the whole memory to install its own code. Anything from the retail code is virtually useless, and shouldn't be relied upon. That being said, doing so will prevent tools from functioning properly, like cheat software, unirom, or even emulators that are sniffing the kernel to do debugging and reporting.

## Legality

Expand Down
58 changes: 5 additions & 53 deletions src/mips/openbios/boot/boot.s
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ _reset:
sw $t0, RAM_SIZE

/* this may be here to let the hardware pick up the new bus settings
before moving on with the actual code. */
before moving on with the actual code. Also, some tools like IDA
or even PCSX-Redux use it as a signature to detect this is a PS1
BIOS file. */
nop
nop
nop
Expand All @@ -71,7 +73,7 @@ _reset:

.ascii "OpenBIOS"

.section .text, "ax", @progbits
.section .text._boot, "ax", @progbits
.align 2
.global _boot
.type _boot, @function
Expand Down Expand Up @@ -106,14 +108,6 @@ _boot:
li $t0, 0x80777
sw $t0, SBUS_DEV8_CTRL

/* Extra from OpenBIOS, not in the original BIOS:
in case we booted from a cart, we move the
flushCache pointer at 0x310 to our own storage,
so we can use it later. */
lw $t0, 0x310($0)
lui $t1, %hi(__flush_cache_real_bios_ptr)
sw $t0, %lo(__flush_cache_real_bios_ptr)($t1)

/* clearing out all registers */
.set push
.set noat
Expand Down Expand Up @@ -227,54 +221,12 @@ bss_init_skip:
stop:
b stop

.section .text._cartBoot, "ax", @progbits
.set noreorder
.global _cartBoot
.global cartBootCop0Hook
.type _cartBoot, @function

_cartBoot:
/* place a rough breakpoint at 0x314, which will capture
the memcpy call writing the A0 table, after it's done
copying the flushCache pointer in memory */
lui $t0, 0b1100101010000000
li $t1, 0x0314
li $t2, 0xffff
mtc0 $0, $7
mtc0 $t1, $5
mtc0 $t2, $9
mtc0 $t0, $7
lui $t9, %hi(cartBootCop0Hook)
lw $t0, (%lo(cartBootCop0Hook)+0x00)($t9)
lw $t1, (%lo(cartBootCop0Hook)+0x04)($t9)
lw $t2, (%lo(cartBootCop0Hook)+0x08)($t9)
lw $t3, (%lo(cartBootCop0Hook)+0x0c)($t9)
sw $t0, 0x40($0)
sw $t1, 0x44($0)
sw $t2, 0x48($0)
/* ironically, what we just did technically requires
calling flushCache, but since our whole point here
is to grab its pointer, we obviously cannot, and
we're going to rely on determinicity instead, which
means some emulators may break on this */
jr $ra
sw $t3, 0x4c($0)

cartBootCop0Hook:
/* and finally, after the above breakpoint triggers,
we jump to _reset in order to boot our own
version of the bios and kernel, but don't
forget to disable the breakpoint, otherwise
we'll be in trouble */
la $t0, _reset
j $t0
mtc0 $0, $7

.global flushCacheFromRealBios
.type flushCacheFromRealBios, @function

flushCacheFromRealBios:
lui $t0, %hi(__flush_cache_real_bios_ptr)
lw $t0, %lo(__flush_cache_real_bios_ptr)($t0)
nop
jr $t0
nop
69 changes: 65 additions & 4 deletions src/mips/openbios/kernel/flushcache.s
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,73 @@ SOFTWARE.

.include "common/hardware/hwregs.inc"

.section .text, "ax", @progbits
/* This flushCache is a variant of the one found in the common/hardware/flushcache.s
file. It is a bit more straightforward as there is no need to ensure that the
code is run from the 0xbfc bios space, since the syscall will ensure that. */

.section .text.flushCache, "ax", @progbits
.align 2
.set noreorder
.global flushCache
.type flushCache, @function

flushCache:
/* Saves the cop0 Status register to $t0. */
mfc0 $t0, $12
/* First, disables interrupts. */
mtc0 $0, $12

/* Writes 0x0001e90c to the BIU_CONFIG register at 0xfffe0130.
This will let us continue to run from uncached memory, while
allowing us to access the i-cache. We keep the constant in
$t2, so we can reuse it later when re-enabling the i-cache. */
li $t5, BIU_CONFIG
li $t2, 0x0001e90c
sw $t2, 0($t5)

/* Isolates the cache, and disables interrupts. */
li $t1, 0x10000
mtc0 $t1, $12

/* Clears only the relevant parts of the i-cache. */
li $t3, 0
li $t4, 0x0f80

1:
sw $0, 0x00($t3)
sw $0, 0x10($t3)
sw $0, 0x20($t3)
sw $0, 0x30($t3)
sw $0, 0x40($t3)
sw $0, 0x50($t3)
sw $0, 0x60($t3)
sw $0, 0x70($t3)
bne $t3, $t4, 1b
addiu $t3, 0x80

/* First, un-isolate the cache. */
mtc0 $0, $12
/* Then, restore the BIU_CONFIG register to 0x0001e988. */
addiu $t2, 0x7c
sw $t2, 0($t5)
/* Finally, restore the cop0 Status register, and return. It
might be unwise to do the mtc0 in the jr delay slot, in
case we arrive back at a cop2 instruction, but further
testing could be useful. */
mtc0 $t0, $12
jr $ra
nop

/* The code below is still kept as a reference, since it was directly reversed
from the retail bios, but it is not used anymore. */

.section .text.flushCacheOriginal, "ax", @progbits
.align 2
.global flushCacheImpl
.type flushCacheImpl, @function
.set reorder
.global flushCacheOriginal
.type flushCacheOriginal, @function

flushCacheImpl:
flushCacheOriginal:
mfc0 $t3, $12
nop

Expand Down
Loading

0 comments on commit 32e74e5

Please sign in to comment.