| 589 | } |
| 590 | |
| 591 | PF_API int pf_vfs_read(const char* vfs_path, uint8_t* buffer, int buffer_size) { |
| 592 | ClearError(); |
| 593 | if (!vfs_path || !g_vfsMounted) { SetError("VFS not mounted or null path"); return 0; } |
| 594 | try { |
| 595 | std::string epath(vfs_path); |
| 596 | std::replace(epath.begin(), epath.end(), '/', '\\'); |
| 597 | const char* lookup = epath.c_str(); |
| 598 | if (*lookup == '\\') lookup++; |
| 599 | |
| 600 | QFBank* bank = QIFStreamB::AutoBank(lookup); |
| 601 | if (!bank) { SetError("File not found in VFS: " + epath); return 0; } |
| 602 | const char* rel = lookup + bank->GetPrefix().GetLength(); |
| 603 | bank->Lock(); |
| 604 | Ref<IFileBuffer> data = bank->Read(rel); |
| 605 | bank->Unlock(); |
| 606 | if (!data || data->GetSize() == 0) { SetError("Failed to read from PBO: " + epath); return 0; } |
| 607 | int size = static_cast<int>(data->GetSize()); |
| 608 | if (!buffer) return size; // query size only |
| 609 | if (size > buffer_size) size = buffer_size; |
| 610 | memcpy(buffer, data->GetData(), size); |
| 611 | return size; |
| 612 | } catch (const std::exception& e) { |
| 613 | SetError(e.what()); |
| 614 | return 0; |
| 615 | } |
| 616 | } |
| 617 | |
| 618 | PF_API PF_HANDLE pf_vfs_image_load(const char* vfs_path) { |
| 619 | ClearError(); |