Разработка и ромхакинг > Ромхакинг
Извлечение данных (видео, звук, музыка) из CD/DVD
<< < (101/101)
Agent Smith:

--- Цитата: Zer0 от 09 Декабря 2025, 23:58:59 --- И раз такой вопрос возник на форуме, в то время как простой поисковой запрос выдаёт искомое
--- Конец цитаты ---
Zer0, ну прям Шерлок Холмс, все дедуктивным методом установил. Закусывать надо.

Я через Яндекс икал и ни чего. Выложил бы сслылку на конкретный сайт тогда
Zer0:
Agent Smith, так ты не озвучил детали, что комп старьё и т.д.  Ещё и в Яндексе ищешь и наверняка на русском  :D Закусывать не мне надо.
Выше дал ссылку. Если соображаешь, то разберёшься.
Томахомэ:
На случай, если кто-то не доверяет рипам Sega Lindbergh'овских игр для Teknoparrot и считает их происхождение каким-то мутным и сомнительным (нередко - очень даже обоснованно, например, когда в самом неожиданном месте находишь какие-то файлы, которые дампер или публикатор явно добавил от себя), первый шаг, чтобы распакованный из CHDюка для MAME ISO хотя бы стал читаемым и монтируемым стандартными программами для работы с образами - откоциваем с помощью HEX-редактора занесённые в начало образа какие-то левые непонятные данные и весь первый том (названный "в честь" идентификационного кода игры), оставляя только 2-й (названный просто LINUX)+$8000 байт перед ним.
На случай, если кто не шарит, ищутся тома по сигнатуре $1,"CD001",$1,$0, а сразу следом - название тома.

Лишь после отставления одного тома LINUX станут видны файлы disk0.img, frontend.set, su1.dat и su2.dat.
Следующий шаг опишу после детальнейшего исследования рома для PIC-шифратора. а с этим есть некоторые проблемы, ибо ничего похожего на карту памяти у PICа в MAMEовском драйвере Lindbergh нет - более того, он там даже не заэмулен как один из процессоров, а ром его занесён в базу пока что чисто "щоби був".

Добавлено 22 декабря 2025 года:

--- Цитата: Томахомэ от 03 Декабря 2025, 16:34:06 ---Небольшой скриптик на Python по извлечению всего дерева файлов из образов для Philips CD-i.
Побочные эффекты: образование пустой папки CDDA, если программа обращается к аудиодорожкам на самом диске как к файлам.

Работоспособность проверена на The Apprentice.

--- Конец цитаты ---

Добавил поддержку однодорожных дисков без прегэпа (в число которых входят Chaos Control и Thunder in Paradise).
Томахомэ:

--- Цитата: Томахомэ от 14 Декабря 2025, 11:49:39 ---На случай, если кто-то не доверяет рипам Sega Lindbergh'овских игр для Teknoparrot и считает их происхождение каким-то мутным и сомнительным (нередко - очень даже обоснованно, например, когда в самом неожиданном месте находишь какие-то файлы, которые дампер или публикатор явно добавил от себя), первый шаг, чтобы распакованный из CHDюка для MAME ISO хотя бы стал читаемым и монтируемым стандартными программами для работы с образами - откоциваем с помощью HEX-редактора занесённые в начало образа какие-то левые непонятные данные и весь первый том (названный "в честь" идентификационного кода игры), оставляя только 2-й (названный просто LINUX)+$8000 байт перед ним.
На случай, если кто не шарит, ищутся тома по сигнатуре $1,"CD001",$1,$0, а сразу следом - название тома.

Лишь после отставления одного тома LINUX станут видны файлы disk0.img, frontend.set, su1.dat и su2.dat.
Следующий шаг опишу после детальнейшего исследования рома для PIC-шифратора. а с этим есть некоторые проблемы, ибо ничего похожего на карту памяти у PICа в MAMEовском драйвере Lindbergh нет - более того, он там даже не заэмулен как один из процессоров, а ром его занесён в базу пока что чисто "щоби був".

--- Конец цитаты ---

Одна только радость - что содержимое рома для PIC здесь уже не просто набор различных данных, как у Naomi и Chihiro, а совершенно-таки чёткий код (см. ниже). Однако, без информации о карте памяти PICа в Lindberg'е полноценный реверс-энжинеринг под сильным вопросом, ибо без неё не понятно, что откуда берётся и куда заносится.
Томахомэ:
По-своему интересный вышел кейс с "Крутыми тачками" (RoadZero) для J2ME. Там вся графика хранится в файлах d[номер файла] без расширения. По сути, каждый представляет собой группу PNG-файлов, объединённых в один последовательно - в открытую, даже никак не запакованных: всего лишь откоцали расширение у имени. Риппинг обошёлся абсолютно без реверса классов или дебага через эмулятор - просто благодаря тому, что, решив удостовериться, что там действительно графика (а больше негде: почти все остальные файлы в JAR'е - либо классы, либо MIDI), глянул в тамошний хекс и обнаружил PNG-сигнатуру.
e2e41:
Добрый день, нужна помощь с компрессорм-декомпрессором, платьформа sega dreamcast, игра deSpiria, контейнер *.cpr
оригинальный пост

--- Цитата ---
--- Цитата: kazetrigger post_id=203387 time=1785010755 user_id=22355 ---I made my own custom tool that incorporates the functionality found in the following projects:

https://github.com/VincentNLOBJ/pvr2image
https://github.com/VincentNLOBJ/PyPVR

You can probably get by with PyPVR for most cases. In the case of deSpiria, it has .CPR files which are LZSS compressed. You'll need to decompress them to PVR first. I found an algorithm to handle that and incorporated that.

The python code for it is as follows (Please note that this code assumes other parts of code are present such as PvrError, so you'll have to tweak the code a bit to get it work. This assumes you have some programming knowledge. If you don't want to raise that custom error, you can raise a standard error or just replace it with print() statements):

--- Код: ---def lzss_decompress(data: bytes) -> bytes:
    if len(data) < 5:
        raise PvrError("LZSS input is too short")

    target_size = struct.unpack_from("<I", data, 0)[0]
    if target_size <= 0:
        raise PvrError(f"invalid LZSS decompressed size: {target_size}")

    ring = bytearray(4096)
    ring_pos = 0xFEE
    src_pos = 4
    out = bytearray()

    while src_pos < len(data) and len(out) < target_size:
        flags = data[src_pos]
        src_pos += 1

        for bit in range(8):
            if flags & (1 << bit):
                # Literal byte
                if src_pos >= len(data):
                    raise PvrError("truncated LZSS literal")

                value = data[src_pos]
                src_pos += 1

                out.append(value)
                ring[ring_pos] = value
                ring_pos = (ring_pos + 1) & 0xFFF

            else:
                # Two-byte back-reference
                if src_pos + 1 >= len(data):
                    raise PvrError("truncated LZSS back-reference")

                b0 = data[src_pos]
                b1 = data[src_pos + 1]
                src_pos += 2

                offset = b0 | ((b1 & 0xF0) << 4)
                length = (b1 & 0x0F) + 3

                for i in range(length):
                    value = ring[(offset + i) & 0xFFF]

                    out.append(value)
                    ring[ring_pos] = value
                    ring_pos = (ring_pos + 1) & 0xFFF

                    if len(out) >= target_size:
                        break

            if len(out) >= target_size:
                break

    if len(out) != target_size:
        raise PvrError(
            f"LZSS stream ended at {len(out):,} bytes; "
            f"expected {target_size:,}"
        )

    return bytes(out)
--- Конец кода ---

Input a CPR's data as bytes and get the bytes out which you can then export to a file.

--- Конец цитаты ---

--- Конец цитаты ---
распаковщик с помощья чата с Алиса ИИ создать удалось
--- Код: ---import struct
import sys

def lzss_decompress(data: bytes) -> bytes:
    print("  [LZSS] Checking input length...")
    if len(data) < 5:
        raise ValueError("LZSS input is too short")

    target_size = struct.unpack_from("<I", data, 0)[0]
    print(f"  [LZSS] Target size from header: {target_size} bytes")
    if target_size <= 0:
        raise ValueError(f"Invalid LZSS decompressed size: {target_size}")

    ring = bytearray(4096)
    ring_pos = 0xFEE
    src_pos = 4
    out = bytearray()

    print("  [LZSS] Starting decompression loop...")
    while src_pos < len(data) and len(out) < target_size:
        flags = data[src_pos]
        src_pos += 1

        for bit in range(8):
            if flags & (1 << bit):
                # Literal byte
                if src_pos >= len(data):
                    raise ValueError("Truncated LZSS literal")

                value = data[src_pos]
                src_pos += 1

                out.append(value)
                ring[ring_pos] = value
                ring_pos = (ring_pos + 1) & 0xFFF
            else:
                # Two-byte back-reference
                if src_pos + 1 >= len(data):
                    raise ValueError("Truncated LZSS back-reference")

                b0 = data[src_pos]
                b1 = data[src_pos + 1]
                src_pos += 2

                offset = b0 | ((b1 & 0xF0) << 4)
                length = (b1 & 0x0F) + 3

                for i in range(length):
                    value = ring[(offset + i) & 0xFFF]
                    out.append(value)
                    ring[ring_pos] = value
                    ring_pos = (ring_pos + 1) & 0xFFF

                    if len(out) >= target_size:
                        break

            if len(out) >= target_size:
                break

    if len(out) != target_size:
        raise ValueError(
            f"LZSS stream ended at {len(out):,} bytes; expected {target_size:,}"
        )

    return bytes(out)

def main():
    print("=== LZSS Decompressor started ===")
    if len(sys.argv) < 3:
        print("Usage: python lzss_decompress.py <input.cpr> <output.bin>")
        sys.exit(1)

    input_path = sys.argv[1]
    output_path = sys.argv[2]

    print(f"[MAIN] Input: {input_path}")
    print(f"[MAIN] Output: {output_path}")

    try:
        with open(input_path, "rb") as f:
            data = f.read()
        print(f"[MAIN] Read {len(data)} bytes from input file")
    except FileNotFoundError:
        print(f"ERROR: Input file not found: {input_path}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"ERROR reading file: {e}", file=sys.stderr)
        sys.exit(1)

    try:
        decompressed = lzss_decompress(data)
        print(f"[MAIN] Decompressed to {len(decompressed)} bytes")
    except ValueError as e:
        print(f"LZSS decompression error: {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"Unexpected error during decompression: {e}", file=sys.stderr)
        sys.exit(1)

    try:
        with open(output_path, "wb") as f:
            f.write(decompressed)
        print(f"[MAIN] Wrote {len(decompressed)} bytes to output file")
        print("=== Done ===")
    except Exception as e:
        print(f"Error writing output file: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
--- Конец кода ---
неудается упаковать полученный *.pvr обратно, помогите если не сложно с реализацией
Sharpnull:

--- Цитата: e2e41 от 02 Августа 2026, 09:58:55 ---нужна помощь с компрессорм-декомпрессором, платьформа sega dreamcast, игра deSpiria, контейнер *.cpr
--- Конец цитаты ---
Это классическое LZSS сжатие. Для такого я переделываю https://github.com/lab313ru/lztoshio, мне лень свой код изменять. Сжатие обычное (можно лучше сжать) и предел размера файла установил 16МиБ. Например, в [PS2] Strawberry Panic! сжатие отличается только заголовком (там есть байты "LZ77" и есть размер сжатых данных).
Вот компрессор. Разжатие:

--- Код: ---lz_deSpriria.exe XMPCYB_A.CPR out.bin d 0
--- Конец кода ---
Сжатие:

--- Код: ---lz_deSpriria.exe out.bin XMPCYB_A_new.CPR c
--- Конец кода ---
e2e41:
благодарю
Навигация
Главная страница сообщений
Предыдущая страница

Перейти к полной версии