Added some HLE calls for torus.elf

Fixed crash related to uninitialized DISPLAY2 register
Added skeleton for disassembler
Forced DMA quadword count to 16-bits
This commit is contained in:
PSI-Rockin 2018-02-02 23:38:04 -05:00
parent 75dbe96d3c
commit 88fde3ec24
10 changed files with 129 additions and 6 deletions

View file

@ -26,7 +26,8 @@ SOURCES += main.cpp \
gs.cpp \
dmac.cpp \
emuwindow.cpp \
gscontext.cpp
gscontext.cpp \
emotiondisasm.cpp
HEADERS += \
emotion.hpp \
@ -39,4 +40,5 @@ HEADERS += \
gs.hpp \
dmac.hpp \
emuwindow.hpp \
gscontext.hpp
gscontext.hpp \
emotiondisasm.hpp

View file

@ -9,6 +9,8 @@ BIOS_HLE::BIOS_HLE(Emulator* e, GraphicsSynthesizer* gs) : e(e), gs(gs)
void BIOS_HLE::hle_syscall(EmotionEngine& cpu, int op)
{
//TODO: what are "negative" BIOS functions, i.e. those with bit 7 set, for?
op &= 0x7F;
switch (op)
{
case 0x02:
@ -20,9 +22,15 @@ void BIOS_HLE::hle_syscall(EmotionEngine& cpu, int op)
case 0x3D:
init_heap(cpu);
break;
case 0x3E:
get_heap_end(cpu);
break;
case 0x71:
set_GS_IMR(cpu);
break;
case 0x7F:
get_memory_size(cpu);
break;
default:
printf("\nUnrecognized HLE syscall $%02X", op);
}
@ -71,8 +79,22 @@ void BIOS_HLE::init_heap(EmotionEngine &cpu)
cpu.set_gpr<uint64_t>(RETURN, thread->heap_base);
}
void BIOS_HLE::get_heap_end(EmotionEngine &cpu)
{
printf("\nSYSCALL: get_heap_end");
thread_hle* thread = &threads[0];
cpu.set_gpr<uint64_t>(RETURN, thread->heap_base);
}
void BIOS_HLE::set_GS_IMR(EmotionEngine &cpu)
{
uint32_t imr = cpu.get_gpr<uint32_t>(PARAM0);
printf("\nSYSCALL: set_GS_IMR $%08X", imr);
}
void BIOS_HLE::get_memory_size(EmotionEngine &cpu)
{
//size of EE RDRAM
printf("\nSYSCALL: get_memory_size");
cpu.set_gpr<uint64_t>(RETURN, 0x02000000);
}

View file

@ -37,7 +37,9 @@ class BIOS_HLE
void set_GS_CRT(EmotionEngine& cpu);
void init_main_thread(EmotionEngine& cpu);
void init_heap(EmotionEngine& cpu);
void get_heap_end(EmotionEngine& cpu);
void set_GS_IMR(EmotionEngine& cpu);
void get_memory_size(EmotionEngine& cpu);
};
#endif // BIOS_HLE_HPP

View file

@ -77,7 +77,6 @@ void DMAC::run()
gs->send_PATH3(quad);
break;
}
}
}
}
@ -173,8 +172,8 @@ void DMAC::write32(uint32_t address, uint32_t value)
channels[GIF].address = value;
break;
case 0x1000A020:
printf("\n[DMAC] GIF QWC: $%08X", value);
channels[GIF].quadword_count = value;
printf("\n[DMAC] GIF QWC: $%08X", value & 0xFFFF);
channels[GIF].quadword_count = value & 0xFFFF;
break;
case 0x1000A030:
printf("\n[DMAC] GIF T_ADR: $%08X", value);

View file

@ -0,0 +1,60 @@
#include <iomanip>
#include <sstream>
#include "emotion.hpp"
#include "emotiondisasm.hpp"
using namespace std;
string EmotionDisasm::disasm_instr(uint32_t instruction, uint32_t instr_addr)
{
if (!instruction)
return "nop";
switch (instruction >> 26)
{
case 0x05:
return disasm_bne(instruction, instr_addr);
case 0x09:
return disasm_addiu(instruction);
}
return "[UNKNOWN]";
}
/*
* Branch disassembly uses "instr_addr", the address of the instruction in memory, to calculate the
* new address that can be branched to.
*/
string EmotionDisasm::disasm_bne(uint32_t instruction, uint32_t instr_addr)
{
//Use stringstream only when putting integers into the disassembly.
stringstream output;
string opcode = "bne";
int offset = (int16_t)(instruction & 0xFFFF);
offset <<= 2;
uint64_t reg1 = (instruction >> 21) & 0x1F;
uint64_t reg2 = (instruction >> 16) & 0x1F;
//EmotionEngine::REG(id) gets the name of the register associated with an id.
output << EmotionEngine::REG(reg1) << ", ";
if (!reg2)
opcode += "z";
else
output << EmotionEngine::REG(reg2) << ", ";
//setfill and setw guarantee that the hexadecimal address has eight hex digits.
output << setfill('0') << setw(8) << hex << (instr_addr + offset + 4);
return opcode + " " + output.str();
}
/*
* addiu doesn't need instr_addr, so it's not included here.
*/
string EmotionDisasm::disasm_addiu(uint32_t instruction)
{
stringstream output;
int16_t imm = (int16_t)(instruction & 0xFFFF);
uint64_t dest = (instruction >> 16) & 0x1F;
uint32_t source = (instruction >> 21) & 0x1F;
output << EmotionEngine::REG(dest) << ", " << EmotionEngine::REG(source) << ", " << imm;
return output.str();
}

View file

@ -0,0 +1,14 @@
#ifndef EMOTIONDISASM_HPP
#define EMOTIONDISASM_HPP
#include <cstdint>
#include <string>
namespace EmotionDisasm
{
std::string disasm_instr(uint32_t instruction, uint32_t instr_addr);
std::string disasm_bne(uint32_t instruction, uint32_t instr_addr);
std::string disasm_addiu(uint32_t instruction);
};
#endif // EMOTIONDISASM_HPP

View file

@ -104,6 +104,9 @@ void EmotionInterpreter::interpret(EmotionEngine &cpu, uint32_t instruction)
case 0x25:
lhu(cpu, instruction);
break;
case 0x27:
lwu(cpu, instruction);
break;
case 0x28:
sb(cpu, instruction);
break;
@ -429,6 +432,17 @@ void EmotionInterpreter::lhu(EmotionEngine &cpu, uint32_t instruction)
cpu.set_gpr<uint64_t>(dest, cpu.read16(addr));
}
void EmotionInterpreter::lwu(EmotionEngine &cpu, uint32_t instruction)
{
int16_t offset = (int16_t)(instruction & 0xFFFF);
uint32_t dest = (instruction >> 16) & 0x1F;
uint32_t base = (instruction >> 21) & 0x1F;
printf("lwu {%d}, %d{%d}", dest, offset, base);
uint32_t addr = cpu.get_gpr<uint32_t>(base);
addr += offset;
cpu.set_gpr<uint64_t>(dest, cpu.read32(addr));
}
void EmotionInterpreter::sb(EmotionEngine &cpu, uint32_t instruction)
{
int16_t offset = (int16_t)(instruction & 0xFFFF);

View file

@ -70,6 +70,7 @@ namespace EmotionInterpreter
void lw(EmotionEngine& cpu, uint32_t instruction);
void lbu(EmotionEngine& cpu, uint32_t instruction);
void lhu(EmotionEngine& cpu, uint32_t instruction);
void lwu(EmotionEngine& cpu, uint32_t instruction);
void sb(EmotionEngine& cpu, uint32_t instruction);
void sh(EmotionEngine& cpu, uint32_t instruction);
void sw(EmotionEngine& cpu, uint32_t instruction);

View file

@ -61,6 +61,12 @@ void GraphicsSynthesizer::reset()
pixels_transferred = 0;
transfer_bit_depth = 32;
num_vertices = 0;
DISPLAY2.width = 640 << 2;
DISPLAY2.height = 224;
DISPFB2.frame_base = 0;
DISPFB2.width = 0;
DISPFB2.x = 0;
DISPFB2.y = 0;
context1.reset();
context2.reset();
current_ctx = &context1;

View file

@ -14,4 +14,7 @@ make
## Using the Emulator
DobieStation requires a copy of the PS2 BIOS, which must be dumped from your PS2, and can only be run from the command line. Loading files from the GUI will be supported in the near future.
DobieStation takes two arguments from the command line: the name of the BIOS file, and the name of an ELF file.
DobieStation takes two arguments from the command line: the name of the BIOS file, and the name of an ELF file.
## Contributing
First, review the [Contribution Guide](../master/CONTRIBUTING.md). Once you have done so, take a look at the [Task List](../master/TASKS.md) and pick something that interests you.