; pattern by w23/yolp
; 128 bytes intro for linux
; code: w23 (me@w23.ru)
;
; somewhat based on (128b) lintro by frag/fsqrt (pzagrebin@gmail.com)
; (which in turn is based on (256b) blin elfom by yolp :D)
;
; http://yolp.omgwtf.ru/
;
; greetings to
; frag/fsqrt
; orbitaldecay
%ifndef W
%define W 1280
%define H 800
%endif
BITS 32
%ifndef SAFE
org 40000h
%else
global _start
%endif
; header overlappery by frag/fsqrt
fd_dsp:
db 7fh, "ELF" ;e_ident ;program header overlapped
dd 1 ;1 = ELFCLASS32 ;p_type, 1 = PT_LOAD
dd 0 ;p_offset
dd $$ ;p_vaddr
dw 2 ;e_type ;p_addr
;2 = ET_EXE
dw 3 ;e_machine
;3 = EM_386
dd _start ;e_version ;p_filesz
;much bigger than actual size but ok
;should be = p_memsz
dd _start ;e_entry ;p_memsz
dd 4 ;e_phoff ;p_flags ; this tiny dword is a huge source of PAIN, as 4 means the section is read-only
;program header offest
_start: ; exactly 8 bytes here for random garbage
push edx ; 1b ; terminating zero for string
push "/dsp" ; 5b ; begin storing device string
jmp short resume ; 2b -- continue running somewhere else
; = 8bytes!
dw 0 ;e_ehsize, (not! :D) surprisingly can be a zero!
dw 20h ;e_phentsize
;pheader size
dw 1 ;e_phnum
; end of essential headers
; what's left is related to section headers, which are none
; e_shentsize
; e_shnum
; e_shstrndx
resume:
;eax = ebx = ecx = edx = esi = edi = 0
push "/dev" ; complete string
; open("/dev/dsp", O_RDWR)
mov ebx, esp
mov cl, 2 ;O_RDWR
mov al, 5 ; open syscall
int 80h ;eax <- fd
push eax ; store for later
; open("/dev/fb0", O_RDRW);
mov al, 5 ; open
mov dword [ebx+4], "/fb0" ; change string to /dev/fb0
int 80h ;eax <- fd
;mmap(NULL, buflen, PROT_WRITE, MAP_SHARED, fd, 0);
push edx ;offset, edx = 0
push eax ;fd
push byte 1 ;MAP_SHARED
mov al, 90 ;mmap syscall number
push eax ; flags
;we need to set second bit for PROT_WRITE, 90 = 01011010
;and setting PROT_WRITE automatically set PROT_READ
push W*H*4 ; framebuffer size (will be reused later)
push edx ;desired address (edx = 0)
mov ebx, esp ;args pointer
int 80h ;eax <- buffer pointer
pop edx ; skip zero, so stack top = fb size
; store framebuffer address
push eax
; now stack contains:
; fb addr
; fb size
; 16 bytes of unreusable garbage
; dsp fd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mainloop:
; pick up and store for next loop
pop edi ; fb addr
pop ecx ; fb size
push ecx
push edi
push esi ;store sample counter
; generate shit
genloop:
mov eax, esi
; all this intro is located in these three tiny instructions
; everything else is just a framework
shr eax, 11
add eax, esi
mul esi
; good but 874 bytes more than limit
; shr eax, 9
; mov ebx, esi
; shr ebx, 13
; or eax, ebx
; mul esi
; store and increment sample count
stosb
inc esi
loop genloop
; restore sample counter
pop esi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; write samples
sndplay:
; write syscall
pop ecx ; ecx = buffer ptr, (push2)
push ecx
mov ebx, [esp+24] ; ebx = fd_dsp
push 4
pop eax ; eax = __NR_write = 4
cdq ; edx = 0
inc dh ; edx = count = 256
add esi, edx ; sample counter += 256
int 0x80
jmp short mainloop