371 lines
No EOL
15 KiB
Text
371 lines
No EOL
15 KiB
Text
логотип, палитра и необходимые управляющие символы.
|
||
|
||
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
|
||
Этот код превратит твою заставку в некое подобие "взломанного терминала". Выглядит очень эффектно для игры про покер или казино! |