Commit Graph

12879 Commits

Author SHA1 Message Date
David Korth
3f1f92b18a [libromdata] IsoPartition: Add basic support for Joliet directories.
If a Supplementary Volume Descriptor is present, check for the Joliet
UCS-2 escape sequences. If found, use the SVD root directory.

Filenames in the SVD root directory are encoded in UCS-2 (big-endian).
The filename length is in bytes, not code points.

NOTE: Currently using a very cheap hack to convert UCS-2 to cp1252,
or more accurately, ISO-8859-1. It's good enough for our purposes
for now. (specifically, getting the icon from AUTORUN.INF.)

TODO: Better character set conversion.
2025-06-08 14:46:56 -04:00
David Korth
a5d22511e0 [libromdata] IsoPartition::readdir(): If there's no more non-zero bytes, return nullptr.
Otherwise, an empty IFst::DirEnt is returned.
2025-06-08 14:44:49 -04:00
David Korth
618c7c6a8d [librptexture] ICO: Fix an implicit cast warning on 64-bit MSVC.
Some checks are pending
Codecov / run (push) Waiting to run
src\librptexture\fileformat\ICO.cpp(642,11): warning C4267: '+=':
	conversion from 'size_t' to 'unsigned int', possible loss of data
2025-06-08 13:07:55 -04:00
David Korth
9a4ab48ccb [libromdata] RomDataFactory: s/exe/ext/
This fixes a Windows build regression from commit 9994c2df94.
([libromdata] RomDataFactory: Explicitly prevent ".ico" and ".cur" from being thumbnailed on Windows.)
2025-06-08 13:05:31 -04:00
David Korth
64fe76a285 [librpbase] exe_res_structs.h: Don't re-define version resource stuff if winver.h is already included.
This should fix the Windows build.
2025-06-08 13:04:12 -04:00
David Korth
993e52084d [librpbase] IResourceReader: New function lookup_resource_ID().
This function takes a zero-based index and returns a resource ID for
the given resource type if it's within range. Otherwise, it returns
a negative POSIX error code.

[libromdata] PEResourceReader, NEResourceReader: Implement it.

[libromdata] EXE: Use lookup_resource_ID for positive icon indexes.

This fixes thumbnailing for discs whose AUTORUN.INF specify a
positive, non-zero icon index.

TODO: Older discs may have truncated ISO-9660 filenames. Need to
parse Joliet file systems, maybe...
2025-06-08 12:44:35 -04:00
David Korth
55cad0ad98 [libromdata] ISO: Parse the icon index for EXE/DLL autorun icons.
The icon index can be:
- 0: First icon
- >0: Zero-based icon index
- <0: Resource ID

EXE: New function loadSpecificIcon() to load an icon given an index.
For iconindex == 0, the icon is cached in d->img_icon.

TODO: Implement a function in IResourceReader to look up a resource ID
from the zero-based index.
2025-06-08 12:23:37 -04:00
David Korth
93e78417e0 [libromdata] ISO: Load AUTORUN.INF icons from EXEs and/or DLLs.
TODO: Handle the icon index.
2025-06-08 11:54:45 -04:00
David Korth
453461e8fb [librptexture] ICOPrivate::loadImage_Win3(): Need to skip the BITMAPINFOHEADER when parsing resource icons.
This fixes the corrupted 128x128 VBoxGuestAdditions.exe icon.
2025-06-08 11:54:34 -04:00
David Korth
f5be3c81a4 [libromdata] EXE: Add icon thumbnailing using librptexture's ICO class.
Uses the first icon in the first available language.

New function loadResourceReader() which ensures rsrcReader is loaded.

[librptexture] ICO: Fix resource loading issues:

- Use the correct resource file pointer, not this->file.
- Add IconRes_Win3 and CursorRes_Win3 cases where appropriate.
- Ensure d->iconType doesn't get overwritten after it's set by the
  ICOPrivate constructor for resources.

FIXME: VBoxWindowsAdditions.exe's PNG icon loads fine, but the 128x128
"regular" icon is corrupted.
2025-06-08 11:40:59 -04:00
David Korth
9994c2df94 [libromdata] RomDataFactory: Explicitly prevent ".ico" and ".cur" from being thumbnailed on Windows.
Also add a note saying EXE shouldn't be registered for thumbnailing,
either.

This will still allow using `rpcli`, and for subclasses to use
EXE to thumbnail e.g. ISO images.
2025-06-08 11:12:06 -04:00
David Korth
6026b40df5 [libromdata] PlayStationDiscPrivate::loadSystemCnf(): Use a constant for the SYSTEM.CNF maximum size. 2025-06-08 02:33:38 -04:00
David Korth
409915591d [libromdata] ISOPrivate::loadIcon(): f_file.reset() isn't needed here. 2025-06-08 02:31:45 -04:00
David Korth
8c5888e9e5 [librptexture] ICO: Rework to support loading from Windows resources.
Some checks are pending
Codecov / run (push) Waiting to run
NOT TESTED; need to add it to the EXE class to test it.
(.ico files still work as they did before.)

Added a constructor that takes an IResourceReaderPtr and the
type/id/lang of the icon. Type should be RT_GROUP_ICON or
RT_GROUP_CURSOR. These are all saved in icodir_res.

The dir union is now initialized in the ICOPrivate constructors,
and is only reset in the ICOPrivate destructor.

loadImage_Win3(): Use a new IRpFilePtr for the icon data.
- For .ico, it's a copy of this->file.
- For Windows executables, it's opened from the IResourceReader.
- Starting address is the icon bitmap address for .ico and
  0 for IResourceReader.
2025-06-08 00:14:28 -04:00
David Korth
d0fb8dc73e [libromdata] ISO::imgpf(): Remove unused RP_D() for now, and an extra 'break;' statement.
In file included from src/libromdata/stdafx.h:63,
                 from src/libromdata/Media/ISO.cpp:10:
src/libromdata/Media/ISO.cpp: In member function ‘virtual uint32_t LibRomData::ISO::imgpf(LibRpBase::RomData::ImageType) const’:
src/libromdata/../common.h:93:45: warning: unused variable ‘d’ [-Wunused-variable]
   93 | #  define RP_D(klass) klass##Private *const d = static_cast<klass##Private*>(d_ptr)
      |                                             ^
src/libromdata/Media/ISO.cpp:984:9: note: in expansion of macro ‘RP_D’
  984 |         RP_D(const ISO);
      |         ^~~~
2025-06-07 23:30:31 -04:00
David Korth
a837c883ee [librptexture] FileFormat_decl.hpp: -'file' 2025-06-07 23:29:08 -04:00
David Korth
44ad904c71 Move IResourceReader from libromdata to librpbase.
This will allow us to use it in librptexture's ICO handler.
2025-06-07 23:26:31 -04:00
David Korth
b3b6eb5b37 [librptexture] CMakeLists.txt: Add ico_structs.h. 2025-06-07 23:19:03 -04:00
David Korth
95bcbc25fb [librptexture] ICO: Use a union of structs containing the different types of directory entries.
This is a bit cleaner than the casting method, though it is a bit messy
at points.

isResource(): Returns true if it's an icon from a resource.
(Currently not set at all...)

reset_dir_union(): Clear the directory union. Called in ICOPrivate's
destructor and various error paths.

TODO: Add resource loading. May need to move IResourceReader from
libromdata to librpbase.
2025-06-07 23:15:15 -04:00
David Korth
821155bd83 [librptexture] ICO: Initial reworking to handle icons from .exe/.dll resources.
ICONDIR and GRPICONDIR are basically the same, but ICONDIRENTRY and
GRPICONDIRENTRY have different sizes. Use an rp::uvector<uint8_t>
and casting to handle this.

Still only supports .ico files for now.
2025-06-07 23:09:45 -04:00
David Korth
e765792ebb [libromdata] ISO: Initial support for AUTORUN.INF icons.
Limitations:
- Only supports .ico, not .exe.
- The filename must match the ISO-9660 filename. Some older Win9x
  discs use a long filename in AUTORUN.INF that's only listed as
  such in the Joliet extension.

Removed some debugging code from the IsoPartition readdir()
implementation testing from earlier.
2025-06-07 22:38:31 -04:00
David Korth
194b3dcf61 [librptexture] fromLinearCI8(): Require 32-bit palettes for all Host_* and Swap_* formats.
TODO:
- More formats?
- Add a table mapping pixel format to bpp?
2025-06-07 22:05:56 -04:00
David Korth
8378697be1 [librptexture] ICOPrivate::loadImage_Win3(): Use Host_ARGB32, not Host_xRGB32, for the palette.
fromLinearCI4() doesn't support Host_xRGB32, and we're filling
in the alpha channel ourselves.

TODO: Add Host_xRGB32 support to fromLinearCI4()?
fromLinearCI8() supports it...

This fixes a regression from commit de802835f7.
([librptexture] ICO: Handle 8-bit color icons.)
2025-06-07 22:03:17 -04:00
David Korth
1caf44d15e [librptexture] ICO: Select the best icon image.
First, the image size is checked. If either width or height are larger
than the previously-selected image, this image is picked. Otherwise,
if the size is identical (both width and height), and bitcount is
higher, then the image is selected.

TODO: Better non-square icon handling? (Use "largest area"?)
2025-06-07 21:50:37 -04:00
David Korth
fbdeae25a5 [librptexture] ICO: Load all of the icon bitmap headers.
Next step is to actually go through them and pick the "best" one.
2025-06-07 21:35:16 -04:00
David Korth
de802835f7 [librptexture] ICO: Handle 8-bit color icons.
- Forgot to move convimg to img when converting from CI8 to ARGB32.

- Make sure sBIT is updated with alpha=1. Otherwise, RpPng::save()
  will tell libpng that there's no alpha, so the resulting PNG image
  saved using `rpcli -x3` won't be transparent.
2025-06-07 21:27:47 -04:00
David Korth
1c96133917 [librptexture] ICO: Divide the bitmap height by 2 for d->dimensions[1].
The ICONDIR height is correct, but the bitmap height is double-sized
because it includes the mask.
2025-06-07 21:19:54 -04:00
David Korth
d01201a184 [librptexture] ICO: Save the icon image header and get sizes for BITMAPCOREHEADER and PNG.
iconHeader is now saved in the private class instead of being loaded
in loadImage_Win3().

The dimensions are now set correctly when an icon's "best" image is
in PNG format.

ico_structs.h: Add PNG chunks.
2025-06-07 21:15:50 -04:00
David Korth
f6e5229b72 [librptexture] ICO: Load PNG-format icon images.
FIXME: Dimensions are still incorrect, since the ICONDIR dimensions
are 0 for 256x256. We should get the dimensions from IHDR instead.
2025-06-07 21:04:18 -04:00
David Korth
fe85d93fc3 [librptexture] ICOPrivate::loadImage_Win3(): Add support for 32-bit ARGB icons.
NOTE: BI_BITFIELDS is not supported right now. (Is that even used for
32-bit ARGB, or is it for 16/24 only?)

Fix mask handling for 48x48 icons by aligning stride to 32-bit.
2025-06-07 20:52:45 -04:00
David Korth
7edb6df2e4 [librptexture] ICOPrivate::loadImage_Win3(): Apply the icon mask for 8bpp and higher icons.
NOTE: Not tested yet!

Remove an unused variable that was used when debugging masks.
The variable counted the number of mask bytes that were processed.
2025-06-07 20:25:16 -04:00
David Korth
eb5300413b [librptexture] ICOPrivate::loadImage_Win3(): Apply the icon mask for 1bpp, 2bpp, and 4bpp icons.
For these icons, an extra transparent color is added.

The image is flipped *after* the mask is applied because the mask is
also upside-down.

TODO:
- Set sBIT.
- Apply the icon mask for CI8 and higher-color icons. (CI8 will need to
  be converted to ARGB32.)
2025-06-07 20:21:22 -04:00
David Korth
37dd0c3ffe [librptexture] ICOPrivate::loadImage_Win3(): Fix mask_data address for upside-down bitmaps.
This seems to place the mask image at the top of the image once it's
flipped, but maybe it's that it's technically two bitmaps and not
one giant bitmap.

TODO: Test it with a right-side up icon.
2025-06-07 20:18:10 -04:00
David Korth
af2c512181 [librptexture] ICO: Initial support for Windows 3.x icons.
The entire icon directory is loaded, but currently the first icon is
loaded instead of selecting the "best" icon.

NOTE: Windows Vista and later determines the "best" icon by looking at
the BITMAPINFOHEADER, not the icon directory. We'll do that too.

loadImage_Win3(): Added support for loading 16-color icons, including
the palette (color table). The mask is loaded, but it isn't applied
yet.

TODO:
- Support more icon formats.
- Apply the mask.
- Determine if the mask isn't present? (e.g. in 32-bit icons)
2025-06-07 19:57:19 -04:00
David Korth
b02a2b8009 [librptexture] ICO: Remove duplicated code from the Qoi handler.
I used Qoi.cpp as a base for ICO.cpp.
2025-06-07 18:29:09 -04:00
David Korth
081d4a4b87 [librptexture] fromLinearMono_WinIcon(): Use white for INVERT.
This at least allows it to show up at all, whereas before it was
showing up as completely transparent.
2025-06-07 18:27:26 -04:00
David Korth
776998d0ed [librptexture] ImageDecoder_Linear_Gray.cpp: New function fromLinearMono_WinIcon().
This converts the Windows 1bpp icon using the mask for transparency.
(Inversion is *not* supported.)

Also, 0 == black, 1 == white. This is the opposite of fromLinearMono(),
which is mostly used for things like VMU icons.

TODO: Handle upside-down images. Win1.x icons and cursors are
right-side up, but Win3.x is upside-down.

ICOPrivate::loadImage_Win1(): Call fromLinearMono_WinIcon().

Tested with the Windows 2.0 DDK icons and cursors, and all of them
appear to be decoding correctly.
2025-06-07 18:24:42 -04:00
David Korth
e84ccfd53d [librptexture] ICO: Initial Windows Icon decoder.
This will eventually be used for ISO image thumbnailing, though it might
also be useful on some other systems.

Linux desktop environments typically have their own ICO thumbnailer.

NOTE: This might still be useful even if the system supports ICO:
- 64-bit Windows cannot read 16-bit Windows executables.
- No current Windows version supports Windows 1.x icons.
- Linux thumbnailers typically don't support Windows 1.x icons, either.

This implementation currently *only* supports Windows 1.x icons, and
doesn't handle masking.

TODO: ImageDecoder::fromLinearMono_WinIcon()?

NOTE: Icon MIME types haven't been added to the XDG files yet, so they
won't be thumbnailed yet (or, more likely, conflict with the system
thumbnailer).
2025-06-07 18:18:24 -04:00
David Korth
e2f0b41964 [libromdata] IsoPartitionPrivate::lookup_int(): Validate isDir in the exact-length match block. 2025-06-07 17:01:13 -04:00
David Korth
c65ea8c0ed [libromdata] IsoPartitionPrivate::getDirectory(): Fail if the entry isn't a directory.
Otherwise, it might try to load the file data as if it's a directory,
which would result in weird shenanigans.
2025-06-07 16:58:07 -04:00
David Korth
988df314e6 [libromdata] IsoPartition: New function sanitize_path() to remove leading and trailing slashes.
This fixes opendir("/NT3x/") for VBoxGuestAdditions.iso.

Note that this may be slightly slower than the old method due to string
copying, but it's much cleaner.

findLastSlash(): Now uses an internal function with a `size` parameter,
and has two wrapper functions: one for `const char*`, and one for
`std::string`.
2025-06-07 16:55:28 -04:00
David Korth
a49fb884f1 [libromdata] IsoPartition: Optimize findLastSlash() by searching for '/' and '\\' at the same time instead of calling strrchr() twice. 2025-06-07 16:39:46 -04:00
David Korth
c7ccd7a39a [librpbase] IsoPartition: Implement opendir(), readdir(), and closedir().
Tested using VBoxGuestAdditions.iso from VirtualBox 7.1.8.

Skip subdirectories with names "\x00" and "\x01". These are Joliet
"special directory identifiers".

IFst:
- Change `dir_idx` from int to intptr_t.
- Add two explicit constructors with a `dir_idx` parameter.
  One takes intptr_t; the other takes void*.
- Added an `extra` parameter for temporary filename storage.
  The ISO-9660 directory entry does not have NULL termination for
  the filename, so we need the temporary buffer to add the terminator.

GcnFst, WiiUFst:
- Update for the `dir_idx` constructor parameter.
- Zero out the `extra` parameter.

TODO:
- Move it to a new IFst subclass, IsoFst?
- Remove the file version number, e.g. ";1"?
- Handle "/NT3x/". Currently, "/NT3x" works, but the trailing slash
  confuses the directory lookup function.
- Joliet subdirectory support?
2025-06-07 16:34:00 -04:00
David Korth
6b30dd5b70 [libromdata] IsoPartition: Mark findLastSlash() and parseTimestamp() as static.
They don't depend on any data in IsoPartitionPrivate.

TODO: HSFS/CDI support?
2025-06-07 15:52:29 -04:00
David Korth
5ed38edbec [libromdata] IFst::readdir(): Return const DirEnt* instead of DirEnt*.
This ensures the caller won't modify the DirEnt.

Note that this doesn't match POSIX readdir(), but we don't need to
strictly match it. (We're also not returning `struct dirent*`; we're
returning a custom one.)
2025-06-07 15:47:30 -04:00
David Korth
b884747254 [librpbase] IFst.hpp: Un-indent the class definition. 2025-06-07 15:27:05 -04:00
David Korth
1aad707f88 [libromdata] WiiUPackagePrivate::addFields_System_XMLs(): Use C strings instead of C++ strings for the XML keys.
Some checks are pending
Codecov / run (push) Waiting to run
CodeQL / Analyze (cpp) (push) Waiting to run
Reduces memory usage slightly and probably improves performance a bit,
since we don't have to manage buffer sizes.

Code size differences: (64-bit Gentoo Linux, gcc-15.1.0, release build, no LTO)

   text    data     bss     dec     hex filename
  15953     288       0   16241    3f71 WiiUPackage_xml.cpp.o [before]
  13376     288       0   13664    3560 WiiUPackage_xml.cpp.o [after]
  -2577       0       0   -2577    -a11 Difference
2025-06-07 15:25:51 -04:00
David Korth
5fd65dc7e2 [kde] AchQtDBus::notifyFunc(): Use QString::arg() for the text.
It's slightly less efficient than manually building the string, but
this lets us reformat the text more easily later on, if needed.

Code size differences: (64-bit Gentoo Linux, gcc-15.1.0, release build, no LTO)

   text    data     bss     dec     hex filename
  14174      72       5   14251    37ab AchQtDBus.cpp.o [kf5] [before]
  14221      72       5   14298    37da AchQtDBus.cpp.o [kf5] [after]
    +47       0       0     +47     +2f Difference

   text    data     bss     dec     hex filename
  12995     200       5   13200    3390 AchQtDBus.cpp.o [kf6] [before]
  13164     200       5   13369    3439 AchQtDBus.cpp.o [kf6] [after]
   +169       0       0    +169     +a9 Difference
2025-06-07 15:20:22 -04:00
David Korth
50ae166484 [kde] RpQt.hpp: New function Q2U8_StdString().
On Qt5 and Qt6, QString::toStdString() converts the string to a UTF-8
std::string, so this simply wraps around that.

On Qt4, QString::toStdString() uses QString::toAscii(), so instead,
we use QString::toUtf8().constData() and convert that into an std::string.

This is more efficient when saving to an std::string, since Q2U8() only
returns the data pointer, which makes it an implicit-length C string.

Q2U8_StdString() is now used wherever an std::string needs to be saved.

Updated all other uses to use Q2U8() instead of QString::toUtf8().constData().

FIXME: RpFileKio::filename():
- Q2U8() returns a temporary, which may be gone by the time this function
  returns...

Code size differences: (64-bit Gentoo Linux, gcc-15.1.0, release build, no LTO)

   text    data     bss     dec     hex filename
  30982    1648      48   32678    7fa6 kfilemetadata_rom-properties-kf5.so [before]
  30846    1648      48   32542    7f1e kfilemetadata_rom-properties-kf5.so [after]
   -136       0       0    -136     -88 Difference

   text    data     bss     dec     hex filename
  26844    1456      48   28348    6ebc overlayiconplugin_rom-properties-kf5.so [before]
  26726    1456      48   28230    6e46 overlayiconplugin_rom-properties-kf5.so [after]
   -118       0       0    -118     -76 Difference

   text    data     bss     dec     hex filename
 599947   21896      64  621907   97d53 rom-properties-kf5.so [before]
 600363   21896      64  622323   97ef3 rom-properties-kf5.so [after]
   +416       0       0    +416    +1a0 Difference

   text    data     bss     dec     hex filename
  55979    2824      48   58851    e5e3 RomThumbnailCreator-kf5.so [before]
  55795    2824      48   58667    e52b RomThumbnailCreator-kf5.so [after]
   -184       0       0    -184     -b8 Difference

   text    data     bss     dec     hex filename
  78593    5144      48   83785   14749 xattrview-kf5.so [before]
  78546    5152      48   83746   14722 xattrview-kf5.so [after]
    -47      +8       0     -39     -27 Difference

   text    data     bss     dec     hex filename
  33049    1760      48   34857    8829 kfilemetadata_rom-properties-kf6.so [before]
  32497    1752      48   34297    85f9 kfilemetadata_rom-properties-kf6.so [after]
   -552      -8       0    -560    -230 Difference

   text    data     bss     dec     hex filename
  28794    1584      48   30426    76da overlayiconplugin_rom-properties-kf6.so [before]
  28350    1568      48   29966    750e overlayiconplugin_rom-properties-kf6.so [after]
   -444     -16       0    -460    -1cc Difference

   text    data     bss     dec     hex filename
 595782   29168      80  625030   98986 rom-properties-kf6.so [before]
 595959   29176      80  625215   98a3f rom-properties-kf6.so [after]
   +177      +8       0    +185     +b9 Difference

   text    data     bss     dec     hex filename
  61854    3352      48   65254    fee6 RomThumbnailCreator-kf6.so [before]
  61649    3360      48   65057    fe21 RomThumbnailCreator-kf6.so [after]
   -205      +8       0    -197     -c5 Difference

   text    data     bss     dec     hex filename
  76033    6224      48   82305   14181 xattrview-kf6.so [before]
  75690    6216      48   81954   14022 xattrview-kf6.so [after]
   -343      -8       0    -351    -15f Difference
2025-06-07 15:15:42 -04:00
David Korth
6577715f73 [librpbase] APNG_dlopen.h: Don't export APNG_ref() and APNG_unref().
It's only used by librpbase internally.

This is technically an ABI break, even though these functions weren't
used outside of librpbase, so bump the SOVERSION to 7.
2025-06-07 14:38:47 -04:00