Перейти к содержимому


Внимание!

Это форум по извлечению ресурсов из игр: музыки, звуков, текстур, 3D-моделей...
Перед поиском ответов на форуме, рекомендуется ознакомиться с основным сайтом EXTRACTOR.ru!
[ Прочтите внимательно - правила создания тем и ответа в них ]
Все вопросы по запуску игр задавайте в другом месте: Установка и запуск игр.


Фотография

Кто даёт частные уроки по програмированию?


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 9

#1 Garrett

Garrett

    Модератор

  • Пользователи
  • 177 сообщений

Отправлено 05 February 2004 - 14:01

Есть великая охота до этого дела - переться в институты уже не охота а курсы - трата времени и денег.
Лучше их заплатить кому - зная что научишься :wink:
пишите у кого есть время для этого
Garrett - собака - imce.ru

#2 pokr

pokr

    Ефрейтор

  • Пользователи
  • 8 сообщений

Отправлено 09 October 2005 - 09:38

Цитата (Garrett @ 5.02.2004 - 18:01)
Есть великая охота до этого дела - переться в институты уже не охота а курсы - трата времени и денег.
Лучше их заплатить кому - зная что научишься :wink:
пишите у кого есть время для этого
Garrett - собака - imce.ru

Возьми пару нормальных книжек (не для чайников), поставь компилятор соответствующий и вперёт полным ходом wink.gif

#3 Terminus

Terminus

    Генерал-майор

  • Администраторы
  • 1969 сообщений
  • Пол:Мужчина
  • Город:Санкт-Петербург

Отправлено 09 October 2005 - 14:34

Прошло полтора года... smile.gif

#4 pokr

pokr

    Ефрейтор

  • Пользователи
  • 8 сообщений

Отправлено 09 October 2005 - 19:46

Цитата (Terminus @ 9.10.2005 - 18:34)
Прошло полтора года... smile.gif

Лучше поздно чем никогда rolleyes.gif biggrin.gif

Год з бодуна не узрел tongue.gif

#5 -=CHE@TER=-

-=CHE@TER=-

    Полковник

  • Администраторы
  • 971 сообщений
  • Пол:Мужчина

Отправлено 15 November 2005 - 19:37

По просьбе товарища Garrett'а.

Microsoft Visual Studio 6.0
File -> New... -> Win32 Console Application
Project name: unqpack
Жмём [OK]
(o) An empty project.
Жмём [Finish]

Теперь в Workspace (такая панелька справа) жмём FileView.
Там выбираем Source File - правой клавишей мышки по нему и Add Files to Folder... Указываем файл unqpack.c и после этого раскрываем Source Files и дублькликаем два раза на этот файл.

Потом жмём F5.
Если это финальная версия программы - то нехило будет уменьшить размер .EXE файла вот тут: Build -> Set Active Configuration... -> unqpack - Win32 Release (после этого нажмите снова F5)
Тогда появится в папке с проектом ещё одна папка - Release - в которой уже будет нормального размера .EXE'шник, которым можно пользоваться).

СРАЗУ ЗАОСТРЮ ВНИМАНИЕ НА ТОМ, ЧТО ТО, ЧТО НОРМАЛЬНО ОТРАЖЕНО ДАЖЕ В САМОЙ ХРЕНОВОЙ СПРАВКЕ - Я НЕ РАСПИСЫВАЛ.
ИМХО: программист - это знание базовых конструкций языка - всё остальное - MSDN. (*улыбается*) MSDN - это более широкое понятие. Проще будет сказать так: программист = это базовые знание конструкция языка + доки по нему или справка. Всё что нужно - начать вращаться на каких-нибудь форумах по нужному языку. Там можно даже не задавая вопросов просматривая старые темы научиться многому и сразу. Хотя писать нормально программы научитесь только со временем. А форумы больше полезны для узнавания Win32API функций, но и там есть "разделы для начинающих" (где-то видел такие, но не заглядывал внутрь).

А вот, собственно, и сама программа:
 
/*
  Распаковщик файлов для игр на движателе от Quake II
  Потел и писал эту программу, а также комментарии к ней -=CHE@TER=-
  http://ctpax-cheater.losthost.org/

  Changelog:
  v1.1 - 2019.08.04
  v1.0 - 2005.11.15
*/

/* вот эти две библиотеки подключаются практически всегда */
#include <stdio.h>
#include <stdlib.h>
/* эта отвечает за функции malloc() и free() - для работы с памятью */
#include <malloc.h>
/* а вот эта нужна, чтобы стала доступна функция создания каталогов mkdir()
   для других (не Win32) платформ используйте dir.h */
#include <direct.h>
/* будем использовать стандартные типы данных, чтобы распаковщик
   был переносим на другие платформы и системы, для современных компиляторов
   достаточно подключить stdint.h:
   #include <stdint.h>
*/
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;

/* oбъявляем структуры для заголовка архива
   и таблицы размещения файлов (FAT) */
#pragma pack(push, 1)
typedef struct {
  uint32_t sign; /* 4 байта - сигнатура архива "PACK" */
  uint32_t offs; /* 4 байта - смещение FAT */
  uint32_t size; /* 4 байта - размер FAT в байтах */
} pak_head;

typedef struct {
  char name[56]; /* 56 байт - ASCIIZ строка, имя файла */
  uint32_t offs; /* 4 байта - смещение файла от начала архива */
  uint32_t size; /* 4 байта - размер этого файла */
} pak_item;
#pragma pack(pop)
/*
  #pragma pack(push, 1) - говорит о том, что поля идут друг за другом без выравнивания
                         (выравнивание задано в 1 байт)
  #pragma pack(pop) - отменяет выравнивание на границу байта
*/

/* В программых на Си - главная функция ВСЕГДА должна называться main() -
именно с неё начинается выполнение программы (всякие извращения типа
WinMain() и прочие - не рассматриваются)
ЗАМЕТКА: это нужно читать документацию, но скажу сразу - что язык Си -
РЕГИСТРОЧУВСТВИТЕЛЬНЫЙ. Это значит, что функция ВСЕГДА пишется так:
main() и ни в каком другом регистре

argc - количество параметров переданных программе
*argv[] - массив строк - этих самых параметров
argc ВСЕГДА >=1 - дело в том, что первый параметр - argv[0] - вернёт имя и путь
исполняемого файла. Например "C:\Games\Quake 2\baseq2\unqpack.exe"
ЗАМЕТКА: в языке Си массивы начинаются с 0-го элемента. */
int main(int argc, char *argv[]) {
/* вспомогательные переменные */
uint32_t i, j, tf;
/* файловые переменные, для работы с файлами */
FILE *fl, *fo;
/* буффер, куда мы будем помещать файлы из архива, перед распаковкой */
uint8_t *buff;
/* структура, куда будет прочитан заголовок архива */
pak_head head;
/* динамический массив - указатель под таблицу размещения файлов
ВНИМАНИЕ: фишка, которая будет показана далее с этим массивом проканает
только для ФИКСИРОВАННОГО РАЗМЕРА структуры pak_item, т.е. там заведомо
НЕТ полей ПЕРЕМЕННОГО размера! */
pak_item *list;
  /* выводим сообщение, что же это за программу мы запустили и какие-нибудь копирайты
     printf() - выводит текст на экран \n - спецсимвол - перевод строки
     ЗАМЕТКА: См. справку по printf(); и его параметрам */
  printf(
    "Quake II Engine .PAK unpacker v1.1\n"
    "(c) CTPAX-X Team 2005, 2019\n"
    "http://www.CTPAX-X.org/\n\n"
  );
  /* если при запуске программы нам ввели не два параметра
     (сама программа и имя входного файла), то выходим
     и сообщаем как правильно пользоваться */
  if (argc != 2) {
    printf("Usage: unqpack.exe <filename.pak>\n\n");
    /* возврящаем код ошибки; в принципе он может быть любой,
       но лучше нумеровать по возрастанию */
    return(1);
  }
  /* открываем файл, который нам передали через командную строку
     файловая_переменная = fopen(имя_файла, строка_режима);
     имя_файла - всё понятно
     строка_режима - состоит из следующих символов:
     r - read - открыть на чтение
     w - write - открыть на запись
     + - открыть для изменения
     t - text - открыть как текстовый файл
     b - binary - открыть как бинарный
     ВНИМАНИЕ!!! ПО УМОЛЧАНИЮ КОМПИЛЯТОРЫ ОТКРЫВАЮТ ФАЙЛЫ КАК ТЕКСТОВЫЕ!!!
     ЧТОБ НЕ ОГРЕСТИ ПРОБЛЕМ - ЯВНО УКАЗЫВАЙТЕ, КАКОЙ ФАЙЛ ВЫ ХОТИТЕ ОТКРЫТЬ -
     ТЕКСТОВЫЙ ИЛИ БИНАРНЫЙ!!!
     Соответственно, эти атрибуты можно комбинировать в строчку как вот тут:
     "rb" - открыть на чтение (r) как бинарный (b) */
  fl = fopen(argv[1], "rb");
  /* блин, а указатель-то пустой - зачит произошла какая-то ошибка при открытии
     (файла нету, неверное имя, доступа нет, и т.д.) - сообщаем об этом и сваливаем */
  if (fl == NULL) {
    printf("Error: can't open input file.\n\n");
    return(2);
  }
  /* читаем из файла:
     fread(адрес_буфера, размер_одного_элемента, кол-во_элементов, файловая_переменная);
     т.е. по в адресу
     адрес_буфера
     будет записано
     размер_одного_элемента * кол-во_элементов
     байт

     sizeof(элемент) - возвращает размер элемента в байтах

     т.к. head - это структура, а НЕ УКАЗАТЕЛЬ, то при помощи операции "&"
     делаем указатель на этот участок памяти. Т.е. обращение:
     uint32_t data;
     data - вернёт нам значение этого типа, которое туда записано
     а обращение:
     &data - вернёт нам АДРЕС, НАЧИНАЯ С КОТОРОГО РАСПОЛОЖЕНА ЭТА ПЕРЕМЕННАЯ

     ЗАМЕТКА: См. справку.
  */
  fread(&head, sizeof(head), 1, fl);
  /* проверяем сигнатуру архива */
  if (head.sign != 0x4B434150) { /* сигнатура "PACK" в шестнадцатеричном виде */
    printf("Erorr: this is not a Quake II Engine .PAK file.\n\n");
    /* закрываем входной файл перед выходом; вообще-то если файл открыт только
    на чтение, т.е. в него не вносились никакие изминения, то его можно и не
    закрывать, но хороший тон требует */
    fclose(fl);
    return(3);
  }
  /* переходим на то место архива, где начинается FAT
  fseek(файловая_переменная, смещение_в_байтах, откада_считать);
  отдельного, пожалуй, внимания заслуживает параметр:
  откуда_считать - он отвечает в прямом смысле откуда считать указанное
  смещение - с НАЧАЛА (SEEK_SET), КОНЦА (см. справку) или ТЕКУЩЕЙ_ПОЗИЦИИ
  (см. там же - я все часто юзаемые константы знаю, но вам не помешает самим
  слазить - лучше запомните) */
  fseek(fl, head.offs, SEEK_SET);
  /* а вот и долгожданный финт ушами -
  размер_всей_структуры / размер_одно_элемента = кол-во_элементов
  tf - это я сократил, от TotalFiles - всего файлов
  АХТУНГ: ещё раз повторяю - это возможно, ТОЛЬКО И ТОЛЬКО, если структура
  архива ФИКСИРОВАННОЙ ДЛИННЫ
  
  отдельный вопрос почему sizeof(list[0]) вместо sizeof(list) ?
  дело в том, что list - это не структура, а УКАЗАТЕЛЬ на структуру,
  поэтому над надо разименовать его, чтобы получить структуру и её размер
  */
  tf = head.size / sizeof(list[0]);
  /* выделяем память под динамический массив:
  кол-во_элементов * размер_одного
  можно было просто вместо этого всего написать:
  malloc(head.size);
  эффект был бы точно такой же, но в данный момент я написал именно так
  для наглядности, ибо архив от какой-нибудь другой игры мог содержать кол-во
  файлов и их структуру без размера всей струкруты, тогда узнав размер
  структуры у одного элемента - элементарно вычисляется размер всего как здесь: */
  list = malloc(tf * sizeof(list[0]));
  /* оба-на! произошла ошибка выделения памяти - вернулась фига - т.е. пустой
  указатель (нехватка памяти, ошибка выделения, и т.д.) */
  if (list == NULL) {
    printf("Erorr: not enough memory for archive FAT.\n\n");
    fclose(fl);
    return(4);
  }
  /* ну и читаем весь заголовок в память:
  sizeof(list[0]) - размер одного элемента заголовка
  tf - количество таких элементов */
  fread(list, sizeof(list[0]), tf, fl);
  /* ну и попёрли в цикле от 0, пока меньше tf (кол-ва_файлов) их по порядку
  перебирать и распаковывать
  ЗАМЕТКА: См. справку по циклу for() */
  for (i = 0; i < tf; i++) {
    /* типа, выводим имя файла, который собираемся распаковать */
    printf("%s - ", list[i].name);
    /* смещаемся к началу этого файла в архиве */
    fseek(fl, list[i].offs, SEEK_SET);
    /* выделям под него память */
    buff = malloc(list[i].size);
    /* проверяем, выделилось там чего-нибудь или нет */
    if (buff == NULL) {
      printf("Error: can't allocate memory for file.\n\n");
      /* ошибка - вышли из цикла, вместо return() чтобы отработал код
      освобождения памяти под FAT и закрытия входного файла после цикла */
      break;
    }
    /* собственно, считываем этот файл в память */
    fread(buff, list[i].size, 1, fl);

    /* а этот жутко долбанный кусок кода нужен чтобы создать все папки
    для распаковки, иначе при создании файла мы вылетим с фатальной ошибкой

    что нужно знать:

    1) все стоки в Си - ASCIIZ - т.е. это набор байтов (массив символов),
       которые идут друг за другом и оканчивается строка на символ 0
       ((Z)ero - ASCII(Z)).

    2) В Си условия if(выражение) считаются ИСТИННЫМИ тогда и только тогда,
       когда:
       условие != 0 (словами: условие НЕ РАВНО !НУЛЮ!)
       т.е. ЛЮБОЕ значение, кроме нуля - это истина.

    теперь объясняю что такое эффективное программирование, и почему оно тут
    используется:
    цикл for(начальное_действие; УСЛОВИЕ_ВЫПОЛНЕНИЯ; промежуточное_действие)
    цикл for() выполнит 1 раз начальное_действие затем будет выполнять
    ПРОМЕЖУТОЧНОЕ_ДЕЙСТВИЕ, пока УСЛОВИЕ_ВЫПОЛНЕНИЯ - ИСТИННО!!!

    начальное условие:
    j = 0; - обнулили счётчик СИМВОЛОВ В СТРОКЕ
    list[i].name - указатель на строку (на начало - первый символ)
    list[i].name[j] - указатель на символ с номером j - Т.Е. КАК ТОЛЬКО
    ОН СТАНЕТ РАВЕН 0 - ЗНАЧИТ СТРОКА - !!КОНЧИЛАСЬ!! ПОТОМУ ЧТО УСЛОВИЕ
    СТАНЕТ - !!ЛОЖНО!! (см. 2) !
    j++; - переходим к следующиму символу, если условие всё ещё истинно

    так чего тут всё-таки делается:
    в цикле идём от первого символа к последнему */
    for (j = 0; list[i].name[j]; j++) {
      /* текущий символ '/' или нет? */
      if (list[i].name[j] == '/') {
        /* если да - то ставим вместо него конец строки */
        list[i].name[j] = 0;
        /* создаём каталог */
        mkdir(list[i].name);
        /* и возвращаем символ обратно
        В Си строки ВСЕГДА заключаются в двойные ковычки!
        Например: "Это строка"
        а ОДИНОЧНЫЕ СИМВОЛЫ - ВСЕГДА !ТОЛЬКО! В ОДИНАРНЫЕ: 'Z' */
        list[i].name[j] = '/';
      }
    }
    /* а теперь поясню, зачем нам был нужен такой головняк с распарсиванием
    каталогов - дело в том, что Quake II хранит имена файлов с путями, например:
    textures/e1u2/troof4_4.wal
    если мы сразу попытаемся такой файл создать, то вылетим с ошибкой,
    так как каталога:
    "textures"
    а уж тем более:
    "textures/e1u2"
    не существует!
    для этого нам нужно создать их вручную! что я и делаю - иду по строке,
    от начала к концу:
    textures/e1u2/troof4_4.wal
    ^
    textures/e1u2/troof4_4.wal
     ^
    (...промежуточные шаги пропущены...)
    textures/e1u2/troof4_4.wal
            ^
    ... создаётся каталог "textures" ....
    textures/e1u2/troof4_4.wal
             ^
    (...промежуточные шаги пропущены...)
    textures/e1u2/troof4_4.wal
                 ^
    так как каталог "textures" УЖЕ СОЗДАН, то мы без проблем можем создать
    каталог "e1u2" внутри него:
    ... создаётся каталог "textures/e1u2" ...
    textures/e1u2/troof4_4.wal
                  ^
    (...промежуточные шаги пропущены...)
    textures/e1u2/troof4_4.wal
                              ^
    дошли до конца строки и вышли */
    /* открываем как бинарный файл на запись и изминения */
    fo = fopen(list[i].name, "wb+");
    if (fo == NULL) {
      printf("\nError: can't create output file.\n\n");
      /* если не получилось - вышли из цикла, но не забыли освободить память */
      free(buff);
      break;
    }
    /* fwrite() - полностью аналогична fread() только ПИШЕТ в файл */
    fwrite(buff, list[i].size, 1, fo);
    /* ну и закрываем его */
    fclose(fo);

    /* всё что выделили - чистим, ибо никто за нас никто это делать не будет,
    а следующий файл уже и не факт, что такого же размера окажется */
    free(buff);
    /* выводим размер распакованного файла (просто так) */
    printf("%u\n", list[i].size);
  }
  /* похвастаемся сколько всего файлов мы смогли извлечь */
  printf("\n\nUnpacked file(s): %u\n", tf);
  /* освобождаем память выделенную под динамический массив для FAT */
  free(list);
  /* закрываем входной файл */
  fclose(fl);
  /* завершаем программу с кодом 0 - проблем не было
  (если не считать ошибок в цикле, которые здесь не обрабатываются) */
  return(0);
}


#6 Garrett

Garrett

    Модератор

  • Пользователи
  • 177 сообщений

Отправлено 16 November 2005 - 09:29

Вот спасибо дружище! smile.gif
а вообще надо, чтоб другие любители поддержали эту колонку smile.gif

#7 ALiEN

ALiEN

    Сержант

  • Пользователи
  • 32 сообщений
  • Город:МУРМАНСК-31

Отправлено 27 April 2006 - 07:57

А тебе не нужны кой-какие материалы по программированию на delphi, pascal, или html? Конечно, не полная информация, но кое-какие советы, описания функций и примеры. rolleyes.gif

#8 CrOm

CrOm

    Старший сержант

  • Пользователи
  • 76 сообщений
  • Город:Omsk

Отправлено 27 April 2006 - 17:43

-=CHE@TER=-

ну это пример консольного проекта. с MFC будет почти совсем по-другому

Garrett

зная хоть какой-нить язык очень легко выучить любой другой.

например: мы знаем язык бейсик (все в школе проходили, надеюсь?)

- изучаем турбо паскаль (после бейсика учится моментально)
стависм себе делфи и начинаем методично копаться в папке Examples. запускаем экспериментируем, смотрим... изучили таки делфи
- ставим себе C++ Builder. он копия делфи, но с сишным акцентом. опять копаемся в исходниках сравниваем с делфи. изучили с++
- ставим себе визуал студию. (а вот тут уже сложнее) даже зная делфи и билдер будет по-началу немного сложно. но опять: копаемся в примерах, смотрим запоминаем, вкуриваем.

сразу оговорюсь: без литературы (КНИГА!!! ибо никакой он-лайн справочник не в состоянии заменить книги лежащей на коленях) невозможно изучить язык в короткие сроки. покупайте книги от солидных авторов! желательно чтобы издание было не первым, а переработынным и дополненыым. чем больше тем лучше smile.gif)) это значит, что книга пользуется успехом и ее авторы постоянно совершенствуют свое творение.

лучшая тренировка - разбор чужих исходников. желательно чтобы они были с комментариями и с описанием. поэтому, ни в коем случае не игнорируем папку Examples! от туда можно почерпнуть вагон знаний

лучший залог результата - усердие и терпение. языки учатся не за пару часов или за 21 день! это только шаблонные операции. но! однажды поняв суть программирования следующие языки пойдут намного легче, особенно, если учесть, что они почти все похожи либо на паскаль, либо на с, либо на бейсик.

а, ну и насчет репетиторства. интернет - не самый лучший для этого полигон.
живое общение и "объяснение на пальцах" не заменят сухие логи протоколов почтовой переписки.

последнее могу подтвердить личным опытом. я преподаю паскаль в ВУЗЕ у первого курса. студенты там всякие: есть сильные, есть такие, которые кроме "музыку включить" и "игрушку запустить" ниче не умели. сейчас они уже вполне в состоянии написать ту программу, которая приведена выше уважаемым г-ном -=CHE@TER=-и это буквально за 10 занятий по 2 часа

удачи

#9 Zmeu

Zmeu

    Младший сержант

  • Пользователи
  • 10 сообщений

Отправлено 22 May 2006 - 20:09

Ты бы спросил сначала может он Delphi учить будет =)
Или ASM !
Ну вот ему парочка примеров :
Fasm -> ASM !
org 256 ;или можно org 100h
mov ah,09
mov dx,text
int 21h
mov ah,10h
int 16h
int 20h

text db 'Privet Eto ASM =))) $'

Или на Delphi
Поскольку я пользуюсь Delphi 2005
То я не знаю и не хочу знать как там в Delphi 3-8
Короче с боку выбираем консольный проект.
В появившемся окне для редактирования кода пишем:

var
I:integer;
f:TFileStream;
s:byte;
begin
I:=$00000000;
s:=$00;
f:=TFileStream.Create('game.exe',fmOpenwrite);
f.Seek(i,sofrombeginning);
f.Write(s,sizeof(s));
repeat
I:=i+$1;
f.Seek(i,sofrombeginning);
f.Write(s,sizeof(s));
until i = $00000255 ;
f.Free;
ShowMessage('100%');
end;

Ну это можно как в консоли так и не в консоли. =)
Тут берётся файл game.exe может быть любой !
И с адреса $00000000 до $00000255 все байты стираем =)
Ну файл конечно работать не будет зато это помогает при расчистке от одного адреса
До Другова когда файл забит ненужным мусором !
Гы . Потом ещё чёнит напишу сейчас в голову ничего не лезет.

#10 Fotosintez

Fotosintez

    Рядовой

  • Пользователи
  • 1 сообщений

Отправлено 21 July 2006 - 11:19

Я могу тебя учить по почте за WM или EGOLD,
сначала я тебе вышлю 5 писем с пятью уроками БЕСПЛАТНО,
там если ты пожелаешь, то договоримся. smile.gif

Сообщение отредактировал Terminus: 23 July 2006 - 18:17