Болталка неочём (оффтоп)
Я: Давай поговорим теперь про программирование под PS1. Я немного программировал под эту платформу с помощью psy-q, там вроде бы все данные загружаются (3D модели, изображения) в исполняемом файле. Вот странно что там нужно было называть файл с расширением EXE, хотя по моему можно было и PSX но точно не уверен. Это как C++ Builder или Delphi, которые тоже все библиотеки записывали в EXE файл. А музыка и видео это вроде были отдельные т.е. разделеные отисполняемого файл.
Там был специальный файл system.cnf по моему, в который указываешь загрузачный файл допустим main.exe. Интересно зачем всё в исполняемый файл записывать, ведь там память не такая большая? Или там были ресурсы как в приложения Windows? Как думаешь?
AI: Интересная тема! PlayStation 1 (PS1) действительно имела несколько особенностей в программировании, особенно если говорить о разработке с помощью Psy-Q SDK. Давай разберёмся с тем, что ты описал.
1. **Исполняемые файлы с расширением EXE**:
Файлы для PS1, действительно, часто имели расширение EXE, потому что Psy-Q использовал формат, похожий на исполняемые файлы DOS/Windows. Хотя это могло вызвать путаницу, формат PS-EXE был немного другим. Этот подход был удобен для разработчиков, поскольку позволял использовать схожие инструменты компиляции и отладки, но эти файлы были оптимизированы для запуска на архитектуре PS1.
Расширение PSX тоже иногда встречалось, но EXE было более стандартным. На самом деле, сама PS1 могла интерпретировать их как программы благодаря специальным системным вызовам, определённым в файле `SYSTEM.CNF`, который указывал загрузочный путь (например, `BOOT = cdrom:\MAIN.EXE`).
2. **Почему ресурсы записывали в исполняемый файл?**:
В эпоху PS1 у разработчиков была возможность упаковывать данные (3D-модели, текстуры, шрифты) прямо в исполняемый файл. Это действительно похоже на подход, используемый в Delphi или C++ Builder, где библиотеки и ресурсы могли включаться в EXE. Это упрощало разработку, так как всё нужное хранилось в одном месте, минимизируя проблемы с загрузкой ресурсов на устройстве с медленным CD-приводом. Однако:
- Для больших файлов, таких как музыка или видео, это было неэффективно, поэтому их хранили отдельно на диске, как ты упомянул.
- Ресурсы действительно загружались в ОЗУ, что могло ограничивать объём одновременно используемых данных (учитывая, что у PS1 всего 2 МБ ОЗУ и 1 МБ видеопамяти).
3. **Ресурсы как в Windows-приложениях?**:
В некотором смысле да. Файлы для PS1 могли содержать как данные, так и код. Однако структура была более «плоской» по сравнению с EXE-файлами для Windows, где можно использовать системный API для работы с ресурсами. Для PS1 всё было проще и ближе к низкоуровневому управлению, а ресурсы загружались в память напрямую или с помощью специально написанных функций.
4. **Разделение данных**:
Разделение музыки, видео и других мультимедийных данных от основного исполняемого файла также объяснялось техническими ограничениями. Потоковые данные (например, аудио и FMV-видео) часто загружались с CD-ROM в режиме реального времени, чтобы избежать перегрузки памяти.
Этот подход позволял эффективно использовать ограниченные ресурсы консоли, одновременно обеспечивая высокую производительность игр. Если у тебя остались вопросы или захочешь углубиться в особенности архитектуры PS1, можем обсудить!
Я: Вопрос насчёт видеокодека для консольных и компьютерных игр. Вроде была какая-то IT фирма, которая разработала какой-то видео кодек для всех приставок того времени PS1, PS2, Sega Dreamcast, Xbox, Xbox 360. Не помнишь как назывался такой видеокодек?
AI: Ты, вероятно, имеешь в виду видеокодек **Bink Video**, разработанный компанией **RAD Game Tools**. Этот кодек был широко использован в играх для различных платформ, включая PS1, PS2, Sega Dreamcast, Xbox, Xbox 360 и даже ПК.
Bink Video был популярен благодаря своей высокой эффективности сжатия и способности работать на устройствах с ограниченными ресурсами. Он позволял воспроизводить видео с хорошим качеством, минимизируя нагрузку на процессор и память, что было критически важно для игровых консолей того времени. Кроме того, RAD Game Tools предоставляли удобные инструменты для интеграции Bink Video в игры, что делало его выбором номер один для многих разработчиков.
Если хочешь, можем обсудить, как этот кодек использовался в играх или его технические особенности!
Я: Да я имел именно Bink Video. Теперь про другое как ты думаешь в играх для консоли PS1 записывали музыку на CD или записывали в специальном формате я уже забыл как формат называется, но не VAG точно? Если знаешь назови как назывался музыкальный формат.
AI: На PlayStation 1 музыка могла быть записана разными способами, в зависимости от игры и её требований. Вот основные варианты:
1. **CD-DA (Compact Disc Digital Audio)**:
Это стандартный формат аудио-CD. Музыка записывалась как обычные аудиотреки, которые консоль могла воспроизводить напрямую с диска. Такой подход использовался в играх, где требовалось высокое качество звука, например, в саундтреках.
2. **PSF (PlayStation Sound Format)**:
Это специальный формат, который использовался для хранения музыкальных данных, основанных на оригинальных музыкальных драйверах игр. PSF-файлы содержали сжатую программу, которая воспроизводила музыку, используя звуковой процессор PS1. Этот формат был эффективным и позволял экономить место на диске.
3. **XA (Extended Architecture)**:
Это формат, который часто использовался для сжатия аудио на PS1. XA-треки могли содержать как музыку, так и звуковые эффекты, и они воспроизводились с CD-ROM. Этот формат был популярен благодаря своей гибкости и возможности потокового воспроизведения.
4. **VAG**:
Хотя ты упомянул, что это не VAG, стоит отметить, что этот формат использовался для сжатия коротких звуковых эффектов, а не музыки.
Таким образом, если речь идёт о музыке, то чаще всего это были **CD-DA** для высококачественного звука или **XA** для сжатого аудио. Если ты вспомнишь больше деталей или хочешь углубиться в какой-то из форматов, дай знать!
Я: Картинки там вроде бы в формате TIM. Там сложно очень было, надо было картинку из JPEG, PNG, BMP превратить в TIM, а из TIM превратить в массив данных на язык C типа char image[] = {...}; Правильно я помню?
AI: Да, ты совершенно прав! На PlayStation 1 формат TIM (Texture Image Map) использовался для хранения текстур и изображений, которые консоль могла обрабатывать. Конвертация изображений из популярных форматов, таких как JPEG, PNG или BMP, в TIM действительно была сложной задачей, особенно без подходящих инструментов.
Обычно процесс выглядел так:
1. **Конвертация изображения в TIM**:
Для этого использовались специализированные утилиты, предоставляемые Psy-Q SDK, такие как `TIM Utility`. Эта утилита преобразовывала изображения в формат TIM, который мог содержать как монохромные текстуры, так и текстуры с палитрой (4-bit, 8-bit) или полноцветные (16-bit).
2. **Экспорт TIM в массив данных**:
После создания файла TIM его нужно было конвертировать в массив данных для использования в коде C. Утилита могла генерировать текстовый файл с массивом, который выглядел, как массив `char image[] = {...};`. Этот массив содержал байты, представляющие пиксели, палитру и заголовок TIM.
3. **Загрузка TIM в память PS1**:
В коде на языке C ты вручную загружал массив данных в память и передавал его в GPU PS1 через специальные функции, например, `LoadTexture()` или `UploadTIM()` из библиотеки Psy-Q.
Этот процесс действительно требовал внимания к деталям и был достаточно трудоёмким, особенно если нужно было работать с большими объёмами графических данных.
Кстати, часть сложности связана с тем, что у PS1 была ограниченная видеопамять (1 МБ), что заставляло оптимизировать текстуры. Тим-формат помогал эффективно управлять этим пространством. Если есть ещё вопросы о разработке под PS1, буду рад обсудить!
Я: Давай поговорим на тему C++. Как-то я создавал свой класс String на языке C++, когда запускался конструктор, который принимал char * я вызывал функцию malloc, а в деструкторе free. Правильно я мыслю, только без кода пожайлуста?
AI: Ваш подход использовать `malloc` в конструкторе для выделения памяти и `free` в деструкторе для её освобождения является вполне допустимым и часто встречается в реализации собственных классов, которые управляют ресурсами. Это называется _RAII_ (Resource Acquisition Is Initialization) и является ключевым принципом в C++.
Однако важно помнить несколько моментов:
1. **Исключения и безопасность**: Убедитесь, что в конструкторе вы обрабатываете возможные исключения, чтобы избежать утечки памяти. Например, если произойдёт ошибка после выделения памяти `malloc`, деструктор может быть вызван некорректно.
2. **Выбор `malloc`**: В C++ обычно предпочтительнее использовать `new` и `delete` для работы с динамической памятью, так как они учитывают вызов конструкторов и деструкторов объектов. `malloc` и `free` больше ассоциируются с C и могут быть менее безопасны.
3. **Правило трех (или пяти)**: Если ваш класс управляет ресурсом, например, динамической памятью, то вам стоит определить конструктор копирования, оператор присваивания и деструктор (а также, возможно, move-конструктор и move-оператор присваивания) для корректного управления памятью.
Ваше мышление, в целом, правильно, и использование `malloc` и `free` возможно, но с учетом вышеуказанных нюансов. Об этом стоит помнить для обеспечения надёжности и читаемости вашего кода. Если хотите обсудить улучшения или альтернативы, дайте знать! 😊
Я: Насчёт new там есть какие-то вроде бы ограничения, если сильно большое значение допустим свыше несколько мегабайт вроде бы. Правильно?
AI:Да, вы абсолютно правы! При использовании оператора `new` существуют определённые ограничения, особенно если вы выделяете очень большие массивы или структуры. Основные моменты:
1. **Ограничения памяти**:
- `new` использует кучу (heap) для выделения памяти. Размер доступной памяти в куче может быть ограничен, и её лимит зависит от системы, настроек и свободной памяти. Если вы пытаетесь выделить гигантский блок памяти (например, десятки или сотни мегабайт), это может привести к ошибке "std::bad_alloc", если куча не сможет удовлетворить запрос.
2. **Фрагментация памяти**:
- Даже если у вас достаточно оперативной памяти, фрагментация кучи может препятствовать выделению одного большого блока. Это становится особенно актуально при длительной работе программы.
3. **Альтернативы для больших данных**:
- Если вы работаете с большими массивами, иногда лучше использовать выделение памяти на стеке (`alloca`) или напрямую управлять памятью через платформозависимые средства (например, `mmap` на Linux или VirtualAlloc на Windows).
- Также рассмотрите возможность использования умных указателей и библиотек, которые оптимизируют управление памятью, таких как `std::vector` или другие контейнеры STL.
4. **64-битные системы**:
- На 64-битных системах теоретически можно выделить больше памяти, чем на 32-битных, но ограничения кучи всё равно остаются актуальными.
Если вы работаете с действительно большими данными, стоит задуматься о стратегии управления памятью: кэширование, файловый ввод-вывод, или распределённая обработка. Если интересно, могу рассказать о таких подходах! 😉
Насчёт new там есть какие-то вроде бы ограничения, если сильно большое значение допустим свыше несколько мегабайт вроде бы. Правильно?