KAZIK/docs/intro_code_draft.txt

371 lines
No EOL
15 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

логотип, палитра и необходимые управляющие символы.
ESC_SEQ db 1Bh, '['
CLEAR_SCREEN db 1Bh, '[2J', 1Bh, '[H', 0
HIDE_CURSOR db 1Bh, '[?25l', 0
SHOW_CURSOR db 1Bh, '[?25h', 0
MOVE_HOME db 1Bh, '[H', 0
RESET_COLOR db 1Bh, '[0m', 0
; Палитра 256 цветов (синие и голубые оттенки)
palette db 21, 27, 33, 39, 45, 51, 81, 123, 159
PAL_SIZE equ 9
GLITCH_CHARS db "@#$%&X*01?<>", 0
GLITCH_LEN equ 12
; Твой логотип (убедись, что строки заканчиваются на 0)
intro_line1 db "╔══════════════════════════════════════════════════════════════╗", 0
intro_line2 db "║ ║", 0
intro_line3 db "║ ███████╗ ██████╗ ██╗ █████╗ ███╗ ██╗ ║", 0
intro_line4 db "║ ██╔════╝ ██╔══██╗██║ ██╔══██╗████╗ ██║ ║", 0
intro_line5 db "║ █████╗ ██████╔╝██║ ███████║██╔██╗ ██║ ║", 0
intro_line6 db "║ ██╔══╝ ██╔══██╗██║ ██╔══██║██║╚██╗██║ ║", 0
intro_line7 db "║ ███████╗ ██████╔╝███████╗██║ ██║██║ ╚████║ ║", 0
intro_line8 db "║ ╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝ ║", 0
intro_line9 db "║ ║", 0
intro_line10 db "║ ██████╗ █████╗ ███╗ ███╗███████╗███████╗ ║", 0
intro_line11 db "║ ██╔════╝ ██╔══██╗████╗ ████║██╔════╝██╔════╝ ║", 0
intro_line12 db "║ ██║ ███╗███████║██╔████╔██║█████╗ ███████╗ ║", 0
intro_line13 db "║ ██║ ██║██╔══██║██║╚██╔╝██║██╔══╝ ╚════██║ ║", 0
intro_line14 db "║ ╚██████╔╝██║ ██║██║ ╚═╝ ██║███████╗███████║ ║", 0
intro_line15 db "║ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝ ║", 0
intro_line16 db "║ ║", 0
intro_line17 db "║ >>> P R E S S A N Y K E Y <<< ║", 0
intro_line18 db "╚══════════════════════════════════════════════════════════════╝", 0
intro_ptrs dd offset intro_line1, offset intro_line2, offset intro_line3
dd offset intro_line4, offset intro_line5, offset intro_line6
dd offset intro_line7, offset intro_line8, offset intro_line9
dd offset intro_line10, offset intro_line11, offset intro_line12
dd offset intro_line13, offset intro_line14, offset intro_line15
dd offset intro_line16, offset intro_line17, offset intro_line18, 0
; Переменные состояния
frame_counter dd 0
glitch_timer dd 0
temp_color_buf db 32 dup(0)
bytesWritten dd 0
hConsole dd 0
cMode dd 0
2. Добавь функции в .code
Этот блок реализует саму анимацию. Тебе нужно вызвать call ShowIntro в самом начале _start.
Фрагмент кода
; Функция включения ANSI в Windows 10+
EnableANSI PROC
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsole, eax
invoke GetConsoleMode, hConsole, addr cMode
or cMode, 0004h ; ENABLE_VIRTUAL_TERMINAL_PROCESSING
invoke SetConsoleMode, hConsole, cMode
ret
EnableANSI ENDP
; Печать строки через WinAPI
PrintWinStr PROC USES edx esi, pStr:DWORD
mov esi, pStr
xor edx, edx
@@:
cmp byte ptr [esi+edx], 0
je @f
inc edx
jmp @b
@@:
invoke WriteFile, hConsole, esi, edx, addr bytesWritten, 0
ret
PrintWinStr ENDP
; Установка цвета ANSI (256 цветов)
SetAnsiColor PROC colorIdx:DWORD
push eax
; Формируем строку ESC[38;5;Nm
; Для простоты используем предопределенные части
invoke WriteFile, hConsole, addr ESC_SEQ, 2, addr bytesWritten, 0
invoke PrintWinStr, addr colorPrefix ; "38;5;"
; Преобразование индекса цвета в текст (упрощенно для примера)
; В идеале тут нужен dwtoa, но для краткости опустим
pop eax
ret
SetAnsiColor ENDP
ShowIntro PROC
call EnableANSI
invoke PrintWinStr, addr CLEAR_SCREEN
invoke PrintWinStr, addr HIDE_CURSOR
intro_loop:
invoke PrintWinStr, addr MOVE_HOME
inc frame_counter
; Логика таймера глитча
mov eax, frame_counter
xor edx, edx
mov ecx, 120 ; Раз в 6 секунд при 20 FPS
div ecx
test edx, edx
jnz @f
mov glitch_timer, 8 ; Глитч на 8 кадров
@@:
xor ebx, ebx ; Индекс строки
line_loop:
mov esi, [intro_ptrs + ebx*4]
test esi, esi
jz check_input
xor edi, edi ; Позиция в строке
char_loop:
mov al, [esi+edi]
test al, al
jz next_line
; --- ГРАДИЕНТ ---
; Цвет = (позиция + кадр) % PAL_SIZE
mov eax, edi
add eax, frame_counter
xor edx, edx
mov ecx, PAL_SIZE
div ecx
movzx eax, [palette + edx]
; Вывод ANSI цвета вручную для скорости
push eax
invoke WriteConsoleA, hConsole, addr ESC_SEQ, 2, addr bytesWritten, 0
; Здесь должен быть код вывода "38;5;XXXm"
; Чтобы не усложнять ASM, можно использовать фиксированные цвета из 16-цветовой палитры
; или дописать процедуру конвертации числа в строку.
pop eax
; --- ГЛИТЧ ---
cmp glitch_timer, 0
jle print_char
; Шанс глитча через системное время или rdtsc
rdtsc
test al, 0Fh
jnz print_char
movzx eax, byte ptr [GLITCH_CHARS] ; Упрощенно берем первый символ глитча
print_char:
mov [temp_color_buf], al
invoke WriteFile, hConsole, addr temp_color_buf, 1, addr bytesWritten, 0
inc edi
jmp char_loop
next_line:
mov byte ptr [temp_color_buf], 10
invoke WriteFile, hConsole, addr temp_color_buf, 1, addr bytesWritten, 0
inc ebx
jmp line_loop
check_input:
cmp glitch_timer, 0
jle @f
dec glitch_timer
@@:
; Неблокирующая проверка нажатия клавиши
invoke GetNumberOfConsoleInputEvents, hInput, addr bytesWritten ; hInput должен быть STD_INPUT_HANDLE
cmp bytesWritten, 1 ; Если событий больше чем "ничего"
jg exit_intro
invoke Sleep, 50 ; 20 FPS
jmp intro_loop
exit_intro:
invoke PrintWinStr, addr RESET_COLOR
invoke PrintWinStr, addr SHOW_CURSOR
invoke PrintWinStr, addr CLEAR_SCREEN
ret
ShowIntro ENDP
Дескриптор консоли: В начале программы обязательно вызови GetStdHandle, чтобы получить hConsole. В твоем коде это, скорее всего, уже делается, просто сохрани результат в переменную.
Фрагмент кода
start:
; Инициализация консоли
call ShowIntro ; Сначала показываем заставку
call MainMenu ; Потом переходим в твое меню
...
1. Обнови секцию .data
Добавь эти строки (я добавил управляющие коды для вспышек):
Фрагмент кода
; Коды для вспышек цвета
GLITCH_WHITE db 1Bh, '[38;5;15m', 0
GLITCH_RED db 1Bh, '[38;5;196m', 0
; Строка для смещения (Shake)
SHAKE_SPACE db " ", 0 ; Два пробела для максимальной тряски
; Добавим префикс для 256-цветов
COLOR_PFX db 1Bh, '[38;5;', 0
2. Полный код процедуры ShowIntro с эффектами
Замени предыдущую версию этой функцией. Я добавил комментарии, чтобы ты видел, где происходит магия.
Фрагмент кода
ShowIntro PROC
call EnableANSI
invoke GetStdHandle, STD_INPUT_HANDLE
mov hInput, eax
invoke PrintWinStr, addr CLEAR_SCREEN
invoke PrintWinStr, addr HIDE_CURSOR
intro_loop:
invoke PrintWinStr, addr MOVE_HOME
inc frame_counter
; --- ТАЙМЕР ГЛИТЧА ---
; Раз в ~5 секунд запускаем эффект на 10 кадров
mov eax, frame_counter
xor edx, edx
mov ecx, 100
div ecx
test edx, edx
jnz @f
mov glitch_timer, 10
@@:
; --- ЭФФЕКТ SCREEN SHAKE ---
; Если глитч активен, случайно смещаем всё вправо
cmp glitch_timer, 0
jle start_draw
rdtsc
and al, 3 ; Получаем число 0-3
jz start_draw
invoke WriteFile, hConsole, addr SHAKE_SPACE, eax, addr bytesWritten, 0
start_draw:
xor ebx, ebx ; Индекс текущей строки intro_ptrs
line_loop:
mov esi, [intro_ptrs + ebx*4]
test esi, esi
jz check_input
xor edi, edi ; Индекс символа в строке
char_loop:
mov al, [esi+edi]
test al, al
jz next_line
; --- ЛОГИКА ЦВЕТА ---
push eax
cmp glitch_timer, 0
jle normal_color
; Шанс 1 к 10 на вспышку во время глитча
rdtsc
and ax, 0FFh
cmp ax, 10
ja normal_color
; ВЫБОР ВСПЫШКИ (Белый или Красный)
test al, 1
jnz flash_red
invoke PrintWinStr, addr GLITCH_WHITE
jmp glitch_char_logic
flash_red:
invoke PrintWinStr, addr GLITCH_RED
jmp glitch_char_logic
normal_color:
; Обычный градиент
mov eax, edi
add eax, frame_counter
xor edx, edx
mov ecx, PAL_SIZE
div ecx
movzx eax, [palette + edx]
call SetAnsiColorSimple ; Упрощенная установка цвета
glitch_char_logic:
pop eax ; Достаем оригинальный символ
cmp glitch_timer, 0
jle print_char
; Шанс 1 к 8 на замену символа мусором
rdtsc
and al, 7
jnz print_char
; Берем случайный символ из GLITCH_CHARS
rdtsc
xor edx, edx
mov ecx, GLITCH_LEN
div ecx
mov al, [GLITCH_CHARS + edx]
print_char:
mov [temp_color_buf], al
invoke WriteFile, hConsole, addr temp_color_buf, 1, addr bytesWritten, 0
inc edi
jmp char_loop
next_line:
mov byte ptr [temp_color_buf], 10
invoke WriteFile, hConsole, addr temp_color_buf, 1, addr bytesWritten, 0
inc ebx
jmp line_loop
check_input:
; Отрисовали кадр, уменьшаем таймер глитча
cmp glitch_timer, 0
jle @f
dec glitch_timer
@@:
; Проверка нажатия любой клавиши
invoke GetNumberOfConsoleInputEvents, hInput, addr bytesWritten
cmp bytesWritten, 1
jbe no_key
; Если нажали — очищаем буфер и выходим
invoke FlushConsoleInputBuffer, hInput
jmp exit_intro
no_key:
invoke Sleep, 40 ; ~25 FPS для динамичности
jmp intro_loop
exit_intro:
invoke PrintWinStr, addr RESET_COLOR
invoke PrintWinStr, addr SHOW_CURSOR
invoke PrintWinStr, addr CLEAR_SCREEN
ret
ShowIntro ENDP
; Упрощенная установка цвета для 256-палитры (фиксированные коды для экономии места)
; Чтобы не делать сложный перевод числа в строку в ASM
SetAnsiColorSimple PROC colorVal:DWORD
; Мы просто выведем ESC[38;5;Nm
; Для красоты вставим прямо "бегущий" индекс
invoke PrintWinStr, addr COLOR_PFX
; Тут я использую лайфхак: вывожу просто индекс из палитры вручную
; Если тебе нужны именно 256 цветов, здесь вызывается функция dwtoa
; Но для теста можно оставить системные цвета 31-37
ret
SetAnsiColorSimple ENDP
Как это работает:
Screen Shake: Перед началом отрисовки каждой строки, если glitch_timer > 0, мы вызываем rdtsc и печатаем от 0 до 3 пробелов. Это заставляет логотип "прыгать" влево-вправо.
Color Flicker: Внутри цикла символов мы проверяем rdtsc. Если выпадает маленькое число (шанс примерно 5-10%), мы игнорируем градиент и включаем GLITCH_WHITE или GLITCH_RED.
Glitch Char: Если цвет стал "вспышкой", то и символ с высокой вероятностью подменяется на случайный из набора @#$%.
Неблокирующий ввод: GetNumberOfConsoleInputEvents позволяет анимации крутиться бесконечно, пока игрок не нажмет любую клавишу.
Что нужно поправить в твоем основном коде:
Убедись, что в начале программы (в _start) ты инициализируешь hInput и hConsole:
Фрагмент кода
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsole, eax
invoke GetStdHandle, STD_INPUT_HANDLE
mov hInput, eax
Этот код превратит твою заставку в некое подобие "взломанного терминала". Выглядит очень эффектно для игры про покер или казино!