Linux x86_64 implementation of libglitch : https://github.com/erlehmann/libglitch.git
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

yaglitch.asm 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. ; yaglitch : Yet Another Glitch
  2. ; Copyright (C) 2018 Weber Yann
  3. ;
  4. ; This program is free software; you can redistribute it and/or modify
  5. ; it under the terms of the GNU General Public License as published by
  6. ; the Free Software Foundation; either version 3 of the License, or
  7. ; any later version.
  8. ;
  9. ; This program is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ;
  17. [bits 64]
  18. %include "sdl.asm"
  19. %include "utils.asm"
  20. %define STACK_SZ 256
  21. %define MAX_FILE_SZ (16 * 17) ; 16 lines of 16 chars + newline chr
  22. %define NL "!"
  23. section .data
  24. op_ptrs: ; pointers on OP functions
  25. dq OP.t ; a
  26. dq OP.put ; b
  27. dq OP.drop ; c
  28. dq OP.mul ; d
  29. dq OP.div ; e
  30. dq OP.add ; f
  31. dq OP.sub ; g
  32. dq OP.mod ; h
  33. dq 0 ; i : syntax error
  34. dq OP.lshift ; j
  35. dq OP.rshift ; k
  36. dq OP.and ; l
  37. dq OP.or ; m
  38. dq OP.xor ; n
  39. dq OP.not ; o
  40. dq OP.dup ; p
  41. dq OP.pick ; q
  42. dq OP.swap ; r
  43. dq OP.lt ; s
  44. dq OP.gt ; t
  45. dq OP.eq ; u
  46. audiospec_wanted: ; SDL_audio configuration
  47. dd 8000 ; freq
  48. dw AUDIO_U8 ; format
  49. db 1 ; channels
  50. db 0 ; silence
  51. dw 0x100 ; samples
  52. dd 0 ; size
  53. dw 0 ; allign
  54. dq audio_cllbck
  55. dq 0 ; userdata
  56. ; text messages
  57. def_str usage, "Usage : "
  58. def_str opts, {" FILE.glitch",0xA}
  59. def_str openerr, {'Error opening file : "', 0xA}
  60. def_str syntax_error, {"Syntax error", 0xA}
  61. def_str bigline_error, {"Line with more than 16 tokens !", 0xA}
  62. def_str nl_error, {"Character \n is not the last one", 0xA}
  63. def_str badop_error, {"Bad OP", 0xA}
  64. window_title: db "Yaglitch", 0x0
  65. section .bss
  66. ; glitch name (1st line) : len 16 + \0
  67. glitch_name: resb 17
  68. ; program internal repr for stack machine
  69. ; each token uses 2 words : 1st for the callback address 2nd for
  70. ; optional value
  71. glitch_pgm: resq 16 * 16 * 2
  72. ; stack machine ring buffer
  73. stack_buff: resd STACK_SZ
  74. ; top of stack pointer
  75. tosp: resq 1
  76. ; stack machine rgister
  77. t: resd 1
  78. ; audiospec returned from SDL
  79. audiospec_recv: resb 32
  80. ; Event receveid from SDL
  81. %ifdef SDL1
  82. event: resb 24
  83. %endif
  84. %ifdef SDL2
  85. event: resb 56
  86. evt_cnt: resb 1
  87. %endif
  88. %ifdef MIX_AUDIO
  89. cllbck_heap: resq 1
  90. cllbck_heapsz: resw 1
  91. %endif
  92. ; Pipe allowing callback to send data to main thread
  93. ipc_pipe:
  94. .rd: resd 1
  95. .wr: resd 1
  96. visu_data_buff: resb 0x100
  97. %ifdef SDL2
  98. visu_win: resq 1
  99. %endif
  100. visu_scr: resq 1
  101. visu_surf: resq 1
  102. section .text
  103. global _start
  104. _start:
  105. ; checking args
  106. mov rcx, [rsp]
  107. cmp rcx, 2
  108. jne exit.badarg
  109. mov rax, 0x2 ; sys_open
  110. mov rdi, [rsp+16] ; argv[1]
  111. xor rsi, rsi ; no flags
  112. xor rdx, rdx ; O_RDONLY
  113. syscall
  114. cmp rax, 0
  115. jl exit.err_open
  116. push rax ; source fd
  117. mov rax, 0xc ; brk
  118. xor rdi, rdi
  119. syscall
  120. push rax ; heap start
  121. mov rdi, rax
  122. add rdi, MAX_FILE_SZ ; new heap end
  123. mov rax, 0xc ; brk
  124. syscall
  125. pop rsi ; heap start
  126. mov r14, rsi
  127. xor rax, rax ; sys_read
  128. mov rdi, [rsp] ; source_fd
  129. mov rdx, MAX_FILE_SZ
  130. syscall
  131. cmp rax, 0
  132. jl exit.err_open
  133. mov r15, rax
  134. mov rax, 0x3 ; sys_close
  135. pop rdi ; source_fd
  136. syscall
  137. mov rbx, r15 ;read size
  138. mov rdi, r14 ; heap start
  139. add rdi, rbx ; heap end
  140. mov r15, rdi
  141. mov rax, 0xc ; brk
  142. syscall ; shrink heap to read size
  143. ; init program space
  144. mov rdi, glitch_pgm
  145. xor rax, rax
  146. stosq
  147. stosq
  148. mov rsi, r14
  149. push rsi
  150. xor r13, r13
  151. xor rbx, rbx
  152. parse:
  153. ; go trhough file , with rsi current ptr, r15 file stop
  154. ; r13 will contain updated lineno and rbx chr in current line
  155. ; rdi store the destination pointer
  156. ; parse glitch name
  157. mov rcx, 16
  158. mov rdi, glitch_name
  159. .name_loop:
  160. inc rbx
  161. lodsb
  162. test al, al ; EOF
  163. jz .no_nl
  164. cmp al, 0xA
  165. je .trailing_nl
  166. cmp al, "!" ; EOL
  167. je .name_end
  168. cmp al, "_"
  169. je .chrname
  170. cmp al, "0"
  171. jl exit.syntax_error
  172. cmp al, "9"
  173. jle .chrname
  174. cmp al, "a"
  175. jl exit.syntax_error
  176. cmp al, "z"
  177. jg exit.syntax_error
  178. .chrname:
  179. stosb
  180. loop .name_loop
  181. jmp exit.bigline
  182. .name_end:
  183. inc r13 ; lineno
  184. xor rbx, rbx
  185. xor al, al
  186. stosb
  187. ; parsing tokens
  188. xor edx, edx ; 32bits numeric token value
  189. xor eax, eax
  190. xor r10, r10 ; numeric token flag (1 mean in numeric token)
  191. xor r11, r11 ; numeric token len
  192. mov rcx, r15
  193. sub rcx, r14
  194. mov rdi, glitch_pgm
  195. .parse_loop:
  196. inc rbx
  197. lodsb
  198. test al, al
  199. jz .no_nl
  200. cmp al, 0xA
  201. je .trailing_nl
  202. cmp al, "!" ; EOL
  203. je .next_line
  204. cmp al, "." ; token separator
  205. je .next_token
  206. cmp al, "0"
  207. jl exit.syntax_error
  208. cmp al, "9"
  209. jle .dec_token
  210. cmp al, "A"
  211. jl exit.syntax_error
  212. cmp al, "F"
  213. jle .hex_token
  214. jmp .op_match ; allowing loop near jump
  215. .end_op:
  216. stosq
  217. xor rax, rax
  218. stosq
  219. loop .parse_loop
  220. .hex_token:
  221. sub al, "A" - 10
  222. jmp .numeric_token
  223. .dec_token:
  224. sub al, "0"
  225. .numeric_token:
  226. cmp r11, 8
  227. je exit.syntax_error ; Numeric constant OF
  228. inc r11
  229. mov r10, 1
  230. shl edx, 4
  231. add edx, eax
  232. loop .parse_loop
  233. .next_token:
  234. test r10, r10 ; check for numeric constant
  235. jnz .add_numeric
  236. loop .parse_loop
  237. .next_line:
  238. inc r13
  239. xor rbx, rbx
  240. .loop_parse_loop:
  241. loop .parse_loop
  242. .add_numeric:
  243. mov rax, OP.numeric
  244. stosq
  245. xor rax, rax
  246. xor r11, r11
  247. xor r10, r10
  248. xchg rax, rdx
  249. shl rax, 32
  250. stosq
  251. xor rax, rax
  252. jmp .loop_parse_loop
  253. .trailing_nl:
  254. ; check that NL is the last chr, else syntax error
  255. cmp rsi, r15
  256. jne exit.nl_not_last
  257. jmp .parse_end
  258. .op_match:
  259. ; allow loop .parse_loop near jump
  260. cmp al, "a"
  261. jl exit.syntax_error
  262. cmp al, "u"
  263. jg exit.syntax_error
  264. ; OP shortand matching
  265. ; checking for previous numeric token to write
  266. test r10, r10
  267. jz .match_op
  268. push rax
  269. ; add previous numeric token
  270. mov rax, OP.numeric
  271. stosq
  272. xor rax, rax
  273. xor r11, r11 ; numeric token length raz
  274. xor r10, r10 ; numeric token flag raz
  275. xchg rax, rdx
  276. shl rax, 32 ; shl to allow reading as dword ?
  277. stosq
  278. pop rax
  279. .match_op:
  280. sub al, "a"
  281. shl rax, 3 ; mul by 8 (size of ptr)
  282. add rax, op_ptrs
  283. mov rax, [rax]
  284. test rax, rax
  285. jz exit.bad_op
  286. jmp .end_op
  287. .no_nl: ; TODO : print warning
  288. ; no NL at EOF
  289. .parse_end:
  290. ; clean heap
  291. mov rax, 0xc
  292. pop rdi
  293. syscall
  294. ; print glitch name
  295. mov rax, "Playing "
  296. push rax
  297. mov rax, 1
  298. mov rdi, 1
  299. mov rsi, rsp
  300. mov rdx, 8
  301. syscall
  302. pop rax
  303. mov rdi, glitch_name
  304. call strlen
  305. mov rdx, rax
  306. mov rax, 1
  307. mov rdi, 1
  308. mov rsi, glitch_name
  309. syscall
  310. mov rax, `\n`
  311. push rax
  312. mov rax, 1
  313. mov rdi, 1
  314. mov rsi, rsp
  315. mov rdx, 1
  316. syscall
  317. pop rax
  318. ; init stack machine runtime
  319. stack_init:
  320. mov rcx, STACK_SZ
  321. mov rdi, stack_buff
  322. xor rax, rax
  323. mov [t], eax
  324. .loop_buff_init:
  325. stosd
  326. loop .loop_buff_init
  327. mov eax, (STACK_SZ - 1) * 4
  328. mov [tosp], eax
  329. sdl_init:
  330. ; Opening IPC pipe
  331. mov rax, 0x16 ; sys_pipe
  332. mov rdi, ipc_pipe
  333. syscall
  334. test rax, rax
  335. jnz exit_fatal
  336. mov rdi, 0x0000FFFF
  337. call SDL_Init
  338. mov rdi, audiospec_wanted
  339. mov rsi, audiospec_recv
  340. call SDL_OpenAudio
  341. ; video init 256*256 window
  342. ; init visu_scr : *screen
  343. %ifdef SDL1
  344. mov rdi, 256
  345. mov rsi, 256
  346. mov rdx, 32
  347. ;mov rcx, SDL_SWSURFACE
  348. mov rcx, SDL_DOUBLEBUF
  349. call SDL_SetVideoMode
  350. call SDL_GetVideoSurface
  351. mov [visu_scr], rax
  352. %endif
  353. %ifdef SDL2
  354. mov rdi, window_title
  355. mov rsi, SDL_WINDOWPOS_UNDEFINED
  356. mov rdx, SDL_WINDOWPOS_UNDEFINED
  357. mov rcx, 256
  358. mov r8, 256
  359. xor r9, r9
  360. call SDL_CreateWindow
  361. mov [visu_win], rax
  362. mov rdi, rax
  363. call SDL_GetWindowSurface
  364. mov [visu_scr], rax
  365. %endif
  366. ; init SDL surface according to SDL screen in visu_surf
  367. xor rdi, rdi ; flasg
  368. mov rsi, 256 ; width
  369. mov rdx, 256 ; height
  370. mov rcx, 32 ; 32 bits depth
  371. mov r8, 0xff ; rmask
  372. mov r9, 0xff00 ; gmask
  373. mov rax, 0xff0000 ; bmask
  374. push rax
  375. push rax
  376. shl rax, 8 ; amask
  377. mov [rsp+8], rax
  378. call SDL_CreateRGBSurface
  379. mov [visu_surf], rax
  380. test rax, rax
  381. jz sdl_error
  382. pop rcx
  383. pop rcx
  384. ; RAZ surface & blit
  385. push rax ; push surface addr
  386. mov rdi, rax
  387. call SDL_LockSurface
  388. %ifdef SDL2
  389. xor rdx, rdx
  390. xor rcx, rcx
  391. MOV_surf_w ecx, visu_surf
  392. xor rax, rax
  393. MOV_surf_pitch eax, visu_surf
  394. mul ecx
  395. MOV_surf_pixels rdi, visu_surf
  396. xor rsi, rsi
  397. ;mov rsi, 0xFF ;white
  398. mov rdx, rax
  399. call SDL_memset ; seems to malloc the pixels
  400. %endif
  401. %ifdef SDL1
  402. xor rcx, rcx
  403. MOV_surf_w ecx, visu_surf
  404. push rcx
  405. MOV_surf_h ecx, visu_surf
  406. MOV_surf_pixels rdi, visu_surf
  407. ;mov rax, 0xffcc22ff ; magenta
  408. ;mov rax, 0xffffffff ; white
  409. dec rcx
  410. .loop_razh:
  411. push rcx
  412. mov rcx, [rsp+8]
  413. dec rcx
  414. .loop_razw:
  415. stosd
  416. loop .loop_razw
  417. pop rcx
  418. loop .loop_razh
  419. pop rcx
  420. %endif
  421. pop rdi ; surface addr
  422. call SDL_UnlockSurface
  423. mov rdi, [visu_surf]
  424. xor rsi, rsi
  425. mov rdx, [visu_scr]
  426. xor rcx, rcx
  427. call SDL_BlitSurface
  428. test rax, rax
  429. jnz sdl_error
  430. %ifdef SDL2
  431. mov rdi, [visu_win]
  432. call SDL_UpdateWindowSurface
  433. %endif
  434. %ifdef SDL1
  435. mov rdi, [visu_scr]
  436. call SDL_Flip
  437. %endif
  438. %ifdef MIX_AUDIO
  439. ; init callback heap infos
  440. mov rax, 0xc ; brk
  441. xor rdi, rdi ; get heap start addr
  442. mov [cllbck_heapsz], rdi
  443. syscall
  444. cmp rax, -1
  445. je exit_fatal
  446. mov [cllbck_heap], rax
  447. %endif
  448. audio_start:
  449. ;start audio
  450. xor rdi, rdi
  451. call SDL_PauseAudio
  452. loop_event:
  453. xor rdi, rdi
  454. mov [event], rdi
  455. mov rdi, event
  456. call SDL_WaitEvent
  457. cmp rax, 0
  458. je sdl_error ; error fetching event...
  459. xor rdi, rdi
  460. %ifdef SDL1
  461. mov dil, [event]
  462. cmp dil, SDL_QUIT
  463. je exit
  464. %endif
  465. %ifdef SDL2
  466. mov edi, [event]
  467. cmp edi, SDL_QUIT
  468. je exit
  469. %endif
  470. evt: ; not exit event
  471. visu:
  472. ; starts by reading from IPC pipe
  473. xor rax, rax ; sys_read
  474. xor rdi, rdi
  475. mov edi, [ipc_pipe.rd]
  476. mov rsi, visu_data_buff
  477. mov rdx, 0x100
  478. syscall
  479. cmp rax, -1
  480. je exit_fatal
  481. jmp loop_event ; loop again
  482. sdl_error:
  483. ; display error & exit
  484. call SDL_GetError
  485. push rax
  486. .dbg:
  487. test rax, rax
  488. jz .no_err
  489. mov rdi, rax
  490. call strlen
  491. .printerr:
  492. mov rdx, rsi ; msglen
  493. pop rdi ; msg
  494. mov rax, 1 ; write
  495. mov rdi, 2 ; stderr
  496. syscall
  497. mov rdi, 0xF
  498. jmp sdl_exit_err
  499. .no_err:
  500. mov rdi, 0x5
  501. jmp sdl_exit_err
  502. exit_fatal:
  503. mov rdi, 42
  504. jmp exit.exit_err
  505. sdl_exit_err:
  506. push rdi
  507. call SDL_Quit
  508. pop rdi
  509. mov rax, 0x3c
  510. syscall
  511. exit:
  512. call SDL_Quit
  513. xor rdi, rdi
  514. mov rax, 0x3c
  515. syscall
  516. .err_open:
  517. mov rax, 1
  518. mov rdi, 2
  519. mov rsi, openerr
  520. mov rdx, openerr_len - 1
  521. syscall
  522. mov rdi, [rsp+16]
  523. push rdi
  524. call strlen
  525. mov rdx, rax
  526. mov rax, 1
  527. mov rdi, 2
  528. pop rsi
  529. syscall
  530. mov rax, 1
  531. mov rdi, 2
  532. mov rsi, openerr + openerr_len - 2
  533. mov rdx, 2
  534. syscall
  535. .badarg:
  536. mov rax, 1
  537. mov rdi, 2
  538. mov rsi, usage
  539. mov rdx, usage_len
  540. syscall
  541. mov rdi, [rsp+8]
  542. call strlen
  543. mov rdx, rax
  544. mov rax, 1
  545. mov rdi, 2
  546. mov rsi, [rsp+8]
  547. syscall
  548. mov rax, 1
  549. mov rdi, 2
  550. mov rsi, opts
  551. mov rdx, opts_len
  552. syscall
  553. mov rdi, 1
  554. .exit_err: ; with rdi error code
  555. mov rax, 0x3c ; exit
  556. syscall
  557. ; expect : r13 lineno, rbx chr num in line
  558. ; TODO: real error message
  559. .nl_not_last:
  560. mov rsi, nl_error
  561. mov rsi, nl_error_len
  562. push qword 3
  563. jmp exit.parse_error
  564. .syntax_error:
  565. mov rsi, syntax_error
  566. mov rdx, syntax_error_len
  567. push qword 2
  568. jmp exit.parse_error
  569. .bigline:
  570. mov rsi, bigline_error
  571. mov rdx, bigline_error_len
  572. push qword 2
  573. jmp exit.parse_error
  574. .bad_op:
  575. mov rsi, badop_error
  576. mov rdx, badop_error_len
  577. push qword 2
  578. jmp exit.parse_error
  579. .parse_error:
  580. ; print error lineno & chrno
  581. push rsi ; source ptr
  582. push rdx
  583. push rbx ; chrno in line
  584. sub r14, rsi ; chr count
  585. push 14
  586. mov rdi, "chr:0x"
  587. mov rsi, 6
  588. call short_err
  589. pop rdi ; chr count
  590. mov rsi, 2
  591. call print_hnum
  592. mov rdi, ",line:0x"
  593. mov rsi, 8
  594. call short_err
  595. mov rdi, r13
  596. mov rsi, 2
  597. call print_hnum
  598. mov rdi, ",col:0x"
  599. mov rsi, 7
  600. call short_err
  601. pop rdi
  602. mov rsi, 2
  603. call print_hnum
  604. mov rdi, ` :\t`
  605. mov rsi, 3
  606. call short_err
  607. pop rdx
  608. pop rsi
  609. mov rax, 1
  610. mov rdi, 2
  611. syscall
  612. pop rdi
  613. jmp exit.exit_err
  614. short_err:
  615. ; rdi is the message (less than 8 chr)
  616. ; rsi is message len
  617. push rdi
  618. mov rdx, rsi
  619. mov rsi, rsp
  620. mov rax, 1
  621. mov rdi, 1
  622. syscall
  623. pop rdi
  624. ret
  625. strlen:
  626. ; rdi containing str pointer
  627. ; rax will contain strlen and rdi is unchanged
  628. mov rsi, rdi
  629. xor rdx, rdx
  630. pushf
  631. cld
  632. .loop:
  633. inc rdx
  634. lodsb
  635. mov cl, al
  636. test al, al
  637. jnz .loop
  638. dec rdx
  639. mov rax, rdx
  640. popf
  641. ret
  642. print_hnum:
  643. ; rdi : number to print
  644. ; rsi : output fd
  645. pushf
  646. mov rax, rdi
  647. xor rcx, rcx
  648. push rcx ; using stack as buffer
  649. std
  650. lea rdi, [rsp + 8]
  651. .loop:
  652. test rax, rax
  653. jz .endloop
  654. inc rcx
  655. inc rcx
  656. push rax
  657. and al, 0x0F
  658. call .al2digit
  659. stosb
  660. mov rax, [rsp]
  661. shr al, 4
  662. call .al2digit
  663. stosb
  664. pop rax
  665. shr rax, 8
  666. jmp .loop
  667. .endloop:
  668. mov rax, 1
  669. xchg rdi, rsi
  670. inc rsi
  671. ;mov rdi, rsi
  672. ;mov rsi, rsp
  673. mov rdx, rcx
  674. syscall
  675. pop rax
  676. popf
  677. ret
  678. .al2digit:
  679. cmp al, 9
  680. jg .hex
  681. add al, "0"
  682. ret
  683. .hex:
  684. add al, "A" - 10
  685. ret
  686. %ifndef MIX_AUDIO
  687. ; simplest/shortes audio_callback : copy byte returned by run_glitch in *stream
  688. audio_cllbck:
  689. ; rdi -> *userdata
  690. ; rsi -> *stream
  691. ; rdx -> stream_len
  692. push rbx
  693. mov rcx, rdx
  694. mov rdi, rsi
  695. push rsi
  696. push rdx
  697. .loop:
  698. push rcx
  699. push rdi
  700. call run_glitch
  701. pop rdi
  702. stosb
  703. pop rcx
  704. inc dword [t]
  705. loop .loop
  706. mov rax, 1 ; write stream data to IPC pipe
  707. xor rdi, rdi
  708. mov edi, [ipc_pipe.wr]
  709. pop rdx
  710. pop rsi
  711. syscall
  712. cmp rax, -1
  713. je exit_fatal
  714. pop rbx
  715. ret
  716. %endif
  717. %ifdef MIX_AUDIO
  718. ; another version of the audio callback using heap to store the data
  719. ; and SDL_MixAudio to copy data in *stream
  720. audio_cllbck:
  721. ; rdi -> *userdata
  722. ; rsi -> *stream
  723. ; rdx -> stream_len
  724. push rbx
  725. mov rcx, [cllbck_heapsz]
  726. cmp rcx, rdx
  727. jl .heap_brk
  728. .continue:
  729. mov rdi, [cllbck_heap]
  730. push rdx ; len
  731. push rdi
  732. push rsi ; *stream, dst
  733. mov rcx, rdx
  734. .pop_loop: ; populating heap with glitch datas
  735. push rcx
  736. push rdi
  737. call run_glitch
  738. pop rdi
  739. stosb
  740. pop rcx
  741. inc dword [t]
  742. loop .pop_loop
  743. pop rdi ; *stream
  744. pop rsi ; heap_start
  745. pop rdx ; len
  746. ;mov rsi, [rsp] ; heap_start
  747. ;mov rdx, [rsp+8] ; len
  748. mov rcx, SDL_MAX_VOLUME
  749. call SDL_MixAudio
  750. ;mov rax, 0x1 ; sys_write
  751. ;mov rdi, [ipc_pipe.wr]
  752. ;pop rsi ; heap_start
  753. ;pop rdx ; len
  754. ;syscall
  755. ;cmp rax, -1
  756. ;je exit_fatal
  757. pop rbx
  758. ret
  759. .heap_brk: ; resize heap to handle
  760. push rdi
  761. push rsi
  762. push rdx
  763. mov rdi, [cllbck_heap]
  764. add rdi, rdx
  765. mov rax, 0xc ; brk
  766. syscall
  767. pop rdx
  768. pop rsi
  769. pop rdi
  770. mov [cllbck_heapsz], rdx
  771. jmp .continue
  772. %endif
  773. run_glitch:
  774. ; Run the glitch_pgm
  775. ; return TOSP value in eax
  776. mov rsi, glitch_pgm
  777. .loop:
  778. lodsq
  779. test rax, rax
  780. jz .end_glitch
  781. push rax
  782. lodsq
  783. mov rdi, rax
  784. pop rax
  785. push rsi
  786. call rax
  787. pop rsi
  788. jmp .loop
  789. .end_glitch:
  790. xor rbx, rbx
  791. mov ebx, [tosp]
  792. lea rdi, [stack_buff + rbx]
  793. mov eax, [rdi]
  794. ; DEBUG (can be use to output data to stdout)
  795. ;push rax
  796. ;xor rdi, rdi
  797. ;mov rdi, rax
  798. ;mov rsi, 1
  799. ;call print_hnum
  800. ;mov rax, " "
  801. ;push rax
  802. ;mov rax, 1
  803. ;mov rdi, 1
  804. ;mov rsi, rsp
  805. ;mov rdx, 1
  806. ;syscall
  807. ;pop rax
  808. ;pop rax
  809. ; /DEBUG
  810. ret
  811. OP:
  812. .numeric:
  813. ; rdi contain the number
  814. shr rdi, 32
  815. ._push:
  816. ; push rdi (edi) on stack_buff
  817. mov eax, edi
  818. xor rbx, rbx
  819. mov ebx, [tosp]
  820. add ebx, 4
  821. cmp ebx, STACK_SZ * 4
  822. jl .go_push
  823. mov ebx, 0
  824. .go_push:
  825. mov [tosp], ebx
  826. lea rdi, [stack_buff+rbx]
  827. stosd
  828. ret
  829. .drop: ; drop just calls pop
  830. ._pop:
  831. ; pop eax from stack_buff
  832. xor rbx, rbx
  833. mov ebx, [tosp]
  834. lea rsi, [stack_buff+rbx]
  835. xor rax, rax
  836. lodsd
  837. test ebx, ebx
  838. jz .pop_no_dec
  839. sub ebx, 4
  840. jmp .pop_end
  841. .pop_no_dec:
  842. mov ebx, (STACK_SZ-1) * 4
  843. .pop_end:
  844. mov [tosp], ebx
  845. ret
  846. .t: ; push t on the stack
  847. mov edi, [t]
  848. call ._push
  849. ret
  850. .put:
  851. pushf
  852. cld
  853. xor rbx, rbx
  854. xor rax, rax
  855. mov ebx, [tosp]
  856. lea rsi, [stack_buff+rbx]
  857. lodsd
  858. and eax, 0xFF
  859. inc eax
  860. mov edx, eax
  861. lodsd
  862. neg rdx
  863. lea rdi, [stack_buff + rdx]
  864. stosq
  865. call OP._pop
  866. popf
  867. ret
  868. .mul:
  869. call .prep_2arg
  870. mul ebx
  871. mov edi, eax
  872. call OP._push
  873. ret
  874. .div:
  875. call .prep_2arg
  876. test ebx, ebx
  877. jz .nodiv
  878. xor rdx, rdx
  879. div ebx
  880. jmp .divend
  881. .nodiv:
  882. xor eax, eax
  883. .divend:
  884. mov edi, eax
  885. call OP._push
  886. ret
  887. .add:
  888. call .prep_2arg
  889. add eax, ebx
  890. mov edi, eax
  891. call OP._push
  892. ret
  893. .sub:
  894. call .prep_2arg
  895. sub eax, ebx
  896. mov edi, eax
  897. call OP._push
  898. ret
  899. .mod:
  900. call .prep_2arg
  901. test rbx, rbx
  902. jz .nomod
  903. xor edx, edx
  904. div ebx
  905. jmp .endmod
  906. .nomod:
  907. xor edx, edx
  908. .endmod:
  909. mov edi, edx
  910. call OP._push
  911. ret
  912. .lshift:
  913. call OP._pop
  914. push rax
  915. call OP._pop
  916. pop rcx
  917. shl eax, cl
  918. mov edi, eax
  919. call OP._push
  920. ret
  921. .rshift:
  922. call OP._pop
  923. push rax
  924. call OP._pop
  925. pop rcx
  926. shr eax, cl
  927. mov edi, eax
  928. call OP._push
  929. ret
  930. .and:
  931. call .prep_2arg
  932. and eax, ebx
  933. mov edi, eax
  934. call OP._push
  935. ret
  936. .or:
  937. call .prep_2arg
  938. or eax, ebx
  939. mov edi, eax
  940. call OP._push
  941. ret
  942. .xor:
  943. call .prep_2arg
  944. xor eax, ebx
  945. mov edi, eax
  946. call OP._push
  947. ret
  948. .not:
  949. call OP._pop
  950. not eax
  951. mov edi, eax
  952. call OP._push
  953. ret
  954. .dup:
  955. call OP._pop
  956. push rax
  957. mov edi, eax
  958. call OP._push
  959. pop rdi
  960. call OP._push
  961. ret
  962. .pick:
  963. call OP._pop
  964. inc eax
  965. and eax, 0xFF
  966. mov ebx, 4
  967. mov ecx, [tosp]
  968. mul ebx ; mul by data size
  969. cmp eax, [tosp]
  970. jg .pick_loop
  971. sub ecx, eax
  972. jmp .pick_lea
  973. .pick_loop: ; eax > tosp
  974. sub eax, ecx
  975. mov ecx, (STACK_SZ - 1) * 4
  976. sub ecx, eax
  977. .pick_lea:
  978. lea rsi, [stack_buff+ecx]
  979. lodsd
  980. push rax
  981. call OP._pop
  982. pop rdi
  983. call OP._push
  984. ret
  985. .swap:
  986. call OP._pop
  987. push rax
  988. call OP._pop
  989. xchg rax, [rsp]
  990. mov edi, eax
  991. call OP._push
  992. pop rdi
  993. call OP._push
  994. ret
  995. .lt:
  996. call .prep_2arg
  997. xor rdi, rdi
  998. cmp eax, ebx
  999. jge .lt_false
  1000. not rdi
  1001. .lt_false:
  1002. call OP._push
  1003. ret
  1004. .gt:
  1005. call .prep_2arg
  1006. xor rdi, rdi
  1007. cmp eax, ebx
  1008. jle .gt_false
  1009. not rdi
  1010. .gt_false:
  1011. call OP._push
  1012. ret
  1013. .eq:
  1014. call .prep_2arg
  1015. xor rdi, rdi
  1016. cmp eax, ebx
  1017. jne .eq_false
  1018. not rdi
  1019. .eq_false:
  1020. call OP._push
  1021. ret
  1022. .prep_2arg:
  1023. ; utils that pop both arguments V1 in eax, V2 in ebx
  1024. call OP._pop
  1025. push rax
  1026. call OP._pop
  1027. pop rbx
  1028. ret