mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
cf05a0ab1f
Recompiler — `recompiler/src/function_analysis.cpp` now stops a function's end_addr at its mapped `jr $ra` + delay slot instead of stretching through trailing data. Fixes Tomba's 0x80076DB0, a real 136-byte function that was being emitted as a psx_unknown_dispatch stub because data after it poisoned the boundary heuristic. `code_generator.cpp` emits `func_<next>(cpu); return;` as a tail call when a mid-function seed split leaves the physical fall-through in a different C function, plus a `debug_server_log_call_entry` at every function entry. `full_function_emitter.cpp` splits dispatch into `psx_dispatch_impl(cpu, addr, stop_addr)` with public `psx_dispatch` and new `psx_dispatch_call(cpu, addr, return_addr)` so JAL/JALR into RAM stubs can return cleanly without growing the native stack. Runtime — `runtime/src/dma.c`/`include/dma.h`/`src/memory.c` now expose `dma_write_masked()`; the 16-bit and 8-bit mmio paths route DICR/DPCR/CHCR partial writes through it so a partial DICR write no longer accidentally clears unrelated channels' pending IRQ flags, and CHCR only triggers DMA when the written mask actually includes the start bit. Unified `complete_transfer(ch)` across all channels, removed `prev_master_flag` edge detection. MDEC (`runtime/src/mdec.c`, `include/mdec.h`) gains a full debug surface: `MDECDebugState` snapshot, an always-on 4096-entry `MDECDebugEvent` ring with 11 event kinds (reset, ctrl_write, cmd_begin/done, decode_done, dma_in/out start/end, output_drained, read_underflow), and `mdec_state` / `mdec_trace` / `mdec_trace_clear` debug-server commands. DMA ch0/1 emit start/end events around MDEC transfers. CDROM (`runtime/src/cdrom.c`, `include/cdrom.h`) — read stream separated from one-shot pending state (`read_cmd`, `read_delay`, `start_read_stream`, `stop_read_stream`, `deliver_read_sector`); `cdrom_state`/`cdrom_trace` report the new fields. Thread/fiber tracing — `traps.c`'s Win32-fiber TCB save/restore now emits 12 thread-event kinds; new `ThreadTraceEntry` ring (64 K) plus `thread_trace` / `thread_trace_clear` debug-server commands report both live CPU regs and the target TCB's full saved register block. wtrace / mmio rings — `WriteTraceEntry` grew (cpu_pc, sp, v0/v1/a0-a3/ t0/t1); capacity 1 M -> 4 M. `MmioTraceEntry` grew (pc, cpu_pc, sp, a0-a3, sr, epc, i_stat, i_mask). Both dump commands accept `count`/`newest=1` for reverse iteration. `restore_trace` and `dirty_block_log` emit extended register fields (a2/a3/sp). Misc — `interrupts.c` polls debug-server every 16K checks so it stays responsive without a separate thread. `psx_runtime.h`'s `call_by_address` routes through `psx_dispatch_call`. Dirty-RAM interp JAL/JALR consult `psx_dispatch_game_compiled` when the game is wired in. iso_reader gains the entry points needed by the game disc path. New `tools/_tomba_probe.py` for port-4470 health checks. Generated — regenerated `SCPH1001_dispatch.c` against the new `psx_dispatch_impl` shape. ISSUES.md — opened Issue #3 (BIOS PS-logo glyph missing on the disc-detected screen, cosmetic). .gitignore — added `recompiler/build-asan*/`, `build-checked/`, `__pycache__/`. Validated end-to-end: BIOS boots, disc detected, Whoopee Camp FMV plays with audio. Frame count advances through ~40K frames without freezes. `unknown_dispatch_log.total = 0`. Remaining FMV cluster issues (1/4-size render, FMV-2 audio missing, no skip) tracked under TombaRecomp/ISSUES.md. Co-Authored-By: Codex (OpenAI) <noreply@openai.com>
171 lines
4.9 KiB
C++
171 lines
4.9 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <vector>
|
|
|
|
/**
|
|
* ISO/BIN/CUE Reader for PS1 CD-ROM images
|
|
* Session 24-25 - Validation-first approach
|
|
*
|
|
* Features:
|
|
* - Open ISO/BIN file
|
|
* - Read sectors by LBA
|
|
* - Parse ISO9660 filesystem
|
|
* - List files in directory
|
|
* - Read file contents by path
|
|
*/
|
|
|
|
namespace PS1 {
|
|
|
|
/**
|
|
* Information about a file entry in the ISO filesystem
|
|
*/
|
|
struct ISOFileEntry {
|
|
std::string name; // Filename (without version suffix)
|
|
uint32_t lba; // Logical Block Address (sector number)
|
|
uint32_t size; // File size in bytes
|
|
bool is_directory; // True if this is a directory
|
|
};
|
|
|
|
/**
|
|
* Root directory information from Primary Volume Descriptor
|
|
*/
|
|
struct RootDirectoryInfo {
|
|
uint32_t lba; // LBA of root directory data
|
|
uint32_t size; // Size of root directory in bytes
|
|
};
|
|
|
|
class ISOReader {
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
ISOReader();
|
|
|
|
/**
|
|
* Destructor - ensures file is closed
|
|
*/
|
|
~ISOReader();
|
|
|
|
/**
|
|
* Open an ISO/BIN file for reading
|
|
* @param filename Path to .iso, .bin, or .cue file
|
|
* @return true if opened successfully, false otherwise
|
|
*/
|
|
bool Open(const std::string& filename);
|
|
|
|
/**
|
|
* Close the currently open file
|
|
*/
|
|
void Close();
|
|
|
|
/**
|
|
* Read a single sector from the ISO
|
|
* @param lba Logical Block Address (sector number)
|
|
* @param buffer Buffer to read into (must be at least 2048 bytes)
|
|
* @return true if read successfully, false otherwise
|
|
*/
|
|
bool ReadSector(uint32_t lba, uint8_t* buffer);
|
|
|
|
/**
|
|
* Read a raw 2352-byte sector from a BIN image.
|
|
* @param lba Logical Block Address (sector number)
|
|
* @param buffer Buffer to read into (must be at least 2352 bytes)
|
|
* @return true if the image stores raw sectors and read succeeded
|
|
*/
|
|
bool ReadRawSector(uint32_t lba, uint8_t* buffer);
|
|
|
|
/**
|
|
* Check if a file is currently open
|
|
* @return true if file is open
|
|
*/
|
|
bool IsOpen() const;
|
|
|
|
/**
|
|
* Get volume ID from Primary Volume Descriptor
|
|
* @return Volume ID string (disc name)
|
|
*/
|
|
std::string GetVolumeID() const;
|
|
|
|
/**
|
|
* Get the resolved path to the BIN file (set after Open())
|
|
*/
|
|
std::string GetBinPath() const;
|
|
|
|
/**
|
|
* Get root directory information
|
|
* @return RootDirectoryInfo containing LBA and size
|
|
*/
|
|
RootDirectoryInfo GetRootDirectory() const;
|
|
|
|
/**
|
|
* List all files in a directory
|
|
* @param path Directory path (empty string = root directory)
|
|
* @return Vector of ISOFileEntry for all files/subdirectories
|
|
*/
|
|
std::vector<ISOFileEntry> ListFiles(const std::string& path = "");
|
|
|
|
/**
|
|
* Find a file by name in the root directory
|
|
* @param path Filename to search for (e.g., "SYSTEM.CNF" or "SCUS_942.36")
|
|
* @param entry Output ISOFileEntry to populate with file info
|
|
* @return true if found, false if not found
|
|
*/
|
|
bool FindFile(const std::string& path, ISOFileEntry& entry);
|
|
|
|
/**
|
|
* Read entire file contents into buffer
|
|
* @param path Filename to read
|
|
* @param buffer Buffer to read into (must be large enough)
|
|
* @param max_size Maximum bytes to read (buffer size limit)
|
|
* @return Number of bytes read (0 if error or file not found)
|
|
*/
|
|
size_t ReadFile(const std::string& path, uint8_t* buffer, size_t max_size);
|
|
|
|
/**
|
|
* Get file size without reading data
|
|
* @param path Filename to query
|
|
* @return File size in bytes (0 if file not found)
|
|
*/
|
|
size_t GetFileSize(const std::string& path);
|
|
|
|
private:
|
|
/**
|
|
* Parse the Primary Volume Descriptor (sector 16)
|
|
* Extracts volume ID and root directory information
|
|
* @return true if parsed successfully, false otherwise
|
|
*/
|
|
bool ParseVolumeDescriptor();
|
|
|
|
/**
|
|
* Helper: Read a 32-bit value in both-endian format (733 format)
|
|
* @param data Pointer to 8-byte both-endian value
|
|
* @return 32-bit value (reads little-endian half)
|
|
*/
|
|
uint32_t Read733(const uint8_t* data) const;
|
|
|
|
/**
|
|
* Helper: Parse a directory record from raw sector data
|
|
* @param data Pointer to directory record data
|
|
* @param entry Output ISOFileEntry to populate
|
|
* @return true if parsed successfully, false if invalid record
|
|
*/
|
|
bool ParseDirectoryRecord(const uint8_t* data, ISOFileEntry& entry) const;
|
|
|
|
/**
|
|
* Helper: List files in a directory given its LBA and size
|
|
* Used for subdirectory navigation
|
|
*/
|
|
std::vector<ISOFileEntry> ListFilesByLBA(uint32_t lba, uint32_t dir_size);
|
|
|
|
std::ifstream file_;
|
|
bool is_open_;
|
|
std::string volume_id_;
|
|
std::string bin_path_;
|
|
RootDirectoryInfo root_dir_;
|
|
};
|
|
|
|
} // namespace PS1
|