Screen.asm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. include_macros equ 1
  2. include_deb_mac equ 1
  3. include_flags equ 1
  4. include include.asm
  5. fade_jump equ 2 ;colour values to jump if fade
  6. scroll_jump equ 16 ;amount to scroll screen by
  7. vga_colours equ 256 ;no of colours on screen
  8. game_colours equ 240 ;don't fade system colours
  9. start32data
  10. backscreen dd ?
  11. original_screen_mode db ? ;screen mode on start up
  12. align 4
  13. work_palette dd ? ;pointer to palette workspace
  14. half_palette dd ? ;temp space for half palette (sssss)
  15. scroll_addr dd 0
  16. scroll_segment dw 0 ;segment pointer to scroll workspace
  17. old_scr_seg dw 0
  18. scroll_dir dd ?
  19. ; System uses colours 240-255
  20. top_16_colours db 0,0,0 ; base black
  21. db 38,38,38 ;63,0,0 ; highlight red
  22. db 63,63,63 ; pointer text white
  23. db 0,0,0
  24. db 0,0,0
  25. db 0,0,0
  26. db 0,0,0
  27. db 54,54,54 ; disk icon
  28. db 45,47,49
  29. db 32,31,41
  30. db 29,23,37
  31. db 23,18,30
  32. db 49,11,11
  33. db 39,5,5
  34. db 29,1,1
  35. db 63,63,63 ; pointer white
  36. end32data
  37. start32save_data
  38. current_palette dd 4316 ;used by control to return the palette
  39. end32save_data
  40. start32code
  41. extrn __x386_mk_protected_ptr:dword
  42. extrn draw_mouse_to_back_screen:near
  43. extrn restore_data_to_back_screen:near
  44. initialise_screen proc
  45. ; Save the current screen mode for later
  46. mov ah,0fh
  47. screen_int ;returns screen mode in al
  48. mov [original_screen_mode],al
  49. mov ax,19 ;Set up the screen mode and clear the screen
  50. screen_int
  51. bts [system_flags],sf_graphics ;flag we are in graphics mode
  52. ; Allocate memory for the back screen
  53. mov eax,full_screen_width*full_screen_height
  54. call my_malloc
  55. mov [backscreen],eax
  56. ; Allocate memory for the game grid
  57. mov eax,GRID_X*GRID_Y*2
  58. call my_malloc
  59. mov [game_grid],eax
  60. ; Set up a descriptor to point to the screen
  61. push 0a0000h
  62. call __x386_mk_protected_ptr ;returns pointer in dx:eax
  63. lea esp,4[esp]
  64. mov [screen_segment],dx
  65. mov ax,3505h ;limit selector to screen
  66. mov bx,dx
  67. mov ecx,full_screen_width*full_screen_height
  68. int 21h
  69. mov eax,vga_colours*3 ;make palette workspace
  70. call my_malloc
  71. mov [work_palette],eax
  72. mov edi,eax ;blank the palette
  73. clear eax
  74. mov ecx,game_colours*3/4
  75. rep stosd
  76. mov esi,offset top_16_colours ;and put system colours in
  77. mov ecx,(vga_colours-game_colours)*3/4
  78. rep movsd
  79. mov esi,[work_palette]
  80. call set_palette
  81. ret
  82. initialise_screen endp
  83. fn_draw_screen proc
  84. ; Set up the new screen.
  85. ; eax holds new palette number
  86. ; ebx holds scroll value
  87. push eax
  88. push ebx
  89. call fn_fade_down
  90. ifdef with_replay
  91. mov eax,-3
  92. mov ebx,[random]
  93. call replay_record_event
  94. endif
  95. call fn_force_refresh ;force full screen update
  96. call re_create
  97. call sprite_engine
  98. call flip
  99. pop ebx
  100. pop eax
  101. call fn_fade_up
  102. ifdef with_replay
  103. call replay_changed_screen
  104. endif
  105. ifdef debug_42
  106. mov [last_speech_file],0
  107. mov [last_speech_screen],200
  108. endif
  109. mov ax,1 ;continue script
  110. ret
  111. fn_draw_screen endp
  112. fn_force_refresh proc
  113. ; Force a full screen update
  114. mov edi,[game_grid]
  115. mov ecx,(GRID_X*GRID_Y)/4
  116. mov eax,80808080h
  117. rep stosd
  118. ret
  119. fn_force_refresh endp
  120. flip proc
  121. bts [mouse_flag],mf_no_update ;hold the mouse interrupt
  122. call draw_mouse_to_back_screen
  123. push es
  124. mov es,[screen_segment]
  125. mov ebx,[game_grid]
  126. mov esi,[backscreen]
  127. clear edi
  128. mov dh,GRID_Y
  129. flip_loop_y: push esi
  130. push edi
  131. mov dl,GRID_X
  132. flip_loop_x: btr wpt [ebx],0 ;check flip flag
  133. jnc no_flip
  134. push esi
  135. push edi
  136. mov eax,GRID_H
  137. move_loop: mov ecx,GRID_W/4
  138. rep movsd
  139. add esi,game_screen_width-GRID_W
  140. add edi,full_screen_width-GRID_W
  141. floop eax,move_loop
  142. pop edi
  143. pop esi
  144. no_flip: inc ebx
  145. add esi,GRID_W
  146. add edi,GRID_W
  147. floop dl,flip_loop_x
  148. pop edi
  149. pop esi
  150. add esi,game_screen_width*GRID_H
  151. add edi,full_screen_width*GRID_H
  152. floop dh,flip_loop_y
  153. pop es
  154. call restore_data_to_back_screen
  155. btr [mouse_flag],mf_no_update ;allow the mouse to move again
  156. ret
  157. flip endp
  158. fn_fade_up proc
  159. ; eax is palette no
  160. ; ebx = 123 for scroll left (going right)
  161. ; ebx = 321 for scroll right (going left)
  162. call check_replay_skip
  163. jc fn_set_palette
  164. bt [system_flags],sf_no_scroll
  165. jc fade
  166. cmp [computer_speed],30000
  167. jc fade
  168. cmp ebx,123
  169. je scroll_left
  170. cmp ebx,321
  171. je scroll_right
  172. fade: ;fade palette from 0 to new palette
  173. mov [current_palette],eax
  174. fetch_compact
  175. jmp fade_up_esi
  176. ; Scrolling
  177. scroll_right: mov [scroll_dir],1
  178. jmp scroll
  179. scroll_left: mov [scroll_dir],0
  180. scroll:
  181. ; next screen should have been drawn to scroll segment. Scroll the screen
  182. ; [screen_segemnt]:0 points to new screen
  183. ; [scroll_segment]:0 points to graphic screen showing old room
  184. push ds
  185. push es
  186. push scroll_jump
  187. fu_start equ 8 ;scroll position
  188. push game_screen_width-scroll_jump
  189. fu_left equ 4 ;bytes to do
  190. push [screen_segment]
  191. fu_screen equ 2
  192. push [scroll_segment]
  193. fu_scroll equ 0
  194. mov ebp,esp
  195. mov es,[scroll_segment] ;it all goes to screen
  196. test [scroll_dir],-1
  197. jne do_right
  198. scroll_screen_l: clear edi
  199. mov esi,scroll_jump ;fu_start[ebp]
  200. clear ebx ;point to new screen
  201. ; Start the scroll at the start of a vertical sync
  202. call get_vsync_flag
  203. jnc not_in_v
  204. call wait_till_out_v_sync
  205. not_in_v: call wait_till_in_v_sync
  206. mov edx,game_screen_height
  207. scroll_loop_l: push esi
  208. push ebx
  209. mov ds,fu_scroll[ebp] ;move screen data along
  210. mov ecx,fu_left[ebp]
  211. rep movsb
  212. mov ds,fu_screen[ebp] ;and fill in with new screen
  213. mov esi,ebx
  214. mov ecx,fu_start[ebp]
  215. rep movsb
  216. pop ebx
  217. add ebx,full_screen_width
  218. pop esi
  219. add esi,full_screen_width
  220. floop edx,scroll_loop_l
  221. ; screen has scrolled one along
  222. add dpt fu_start[ebp],scroll_jump
  223. sub dpt fu_left[ebp],scroll_jump
  224. jnc scroll_screen_l
  225. jmp scroll_done
  226. do_right: std
  227. scroll_screen_r: mov edi,game_screen_width-1
  228. mov esi,game_screen_width-scroll_jump-1
  229. mov ebx,edi ;point to new screen
  230. mov edx,game_screen_height
  231. scroll_loop_r: push edi
  232. push esi
  233. push ebx
  234. mov ds,fu_scroll[ebp] ;move screen data along
  235. mov ecx,fu_left[ebp]
  236. rep movsb
  237. mov ds,fu_screen[ebp] ;and fill in with new screen
  238. mov esi,ebx
  239. mov ecx,fu_start[ebp]
  240. rep movsb
  241. pop ebx
  242. add ebx,full_screen_width
  243. pop esi
  244. add esi,full_screen_width
  245. pop edi
  246. add edi,full_screen_width
  247. floop edx,scroll_loop_r
  248. ; screen has scrolled one along
  249. add dpt fu_start[ebp],scroll_jump
  250. sub dpt fu_left[ebp],scroll_jump
  251. jnc scroll_screen_r
  252. cld
  253. scroll_done: lea esp,12[esp]
  254. pop es
  255. pop ds
  256. ; now swap around the segments
  257. mov bx,[scroll_segment]
  258. xchg bx,[screen_segment]
  259. mov ax,3502h
  260. int 21h
  261. mov [scroll_segment],0
  262. mov eax,[scroll_addr]
  263. call my_free
  264. mov al,1
  265. ret
  266. fn_fade_up endp
  267. fade_up_esi proc
  268. ; esi points to new palette
  269. mov edx,64-fade_jump
  270. call wait_50hz ;try and work to 50hz
  271. fade_loop: push esi
  272. push edx
  273. mov ecx,game_colours*3 ;rgb for each colour
  274. mov edi,[work_palette] ;what we are working from
  275. col_loop: lodsb ;where we want to get
  276. sub al,dl ;show it yet?
  277. jc no_show
  278. mov [edi],al
  279. no_show: inc edi
  280. loop col_loop
  281. mov esi,[work_palette] ;what we are working from
  282. call set_palette
  283. call wait_50hz
  284. pop edx
  285. pop esi
  286. sub edx,fade_jump
  287. jnc fade_loop
  288. ; Copy the palette accross to make sure it is ok
  289. mov edi,[work_palette]
  290. mov ecx,game_colours*3/4
  291. rep movsd
  292. mov esi,[work_palette]
  293. call set_palette ;set real palette (not work space)
  294. ;mov esi,offset top_16_colours ;and put system colours in
  295. ;mov ecx,(vga_colours2-fade_colours2)*3/4
  296. ;rep movsd
  297. ; fade done
  298. ret
  299. fade_up_esi endp
  300. fn_fade_down proc
  301. ; if ebx is 123 or 321 then we want to scroll
  302. call check_replay_skip
  303. jnc not_skip
  304. ret
  305. not_skip: bt [system_flags],sf_no_scroll
  306. jc fade
  307. cmp [computer_speed],30000
  308. jc fade
  309. cmp ebx,123
  310. je scroll
  311. cmp ebx,321
  312. jne fade
  313. scroll: ;create a new screen pointer so new screen is drawn to memory and not screen
  314. mov eax,full_screen_width*full_screen_height
  315. call my_malloc ;allocate space for next screen
  316. mov [scroll_addr],eax
  317. mov ax,3501h ;make a selector
  318. int 21h
  319. mov [scroll_segment],bx
  320. mov bx,ds ;calculate base address of screen
  321. mov ax,3504h
  322. int 21h
  323. add ecx,[scroll_addr]
  324. mov ax,3503h ;set address for scroll segment
  325. mov bx,[scroll_segment]
  326. int 21h
  327. mov bx,[scroll_segment] ;point screen segment to this work space
  328. xchg bx,[screen_segment]
  329. mov [scroll_segment],bx
  330. jmp done
  331. fade: ;take palette at workspace down to 0
  332. mov ecx,64/fade_jump
  333. call wait_50hz ;try and work to 50hx
  334. fade_loop: push ecx
  335. mov esi,[work_palette]
  336. mov ecx,3*game_colours
  337. col_loop: test bpt[esi],-1 ;already at 0?
  338. je is_0
  339. sub bpt[esi],fade_jump ;going down
  340. jnc is_0
  341. mov bpt[esi],0 ;compensate for underflow
  342. is_0: inc esi
  343. loop col_loop
  344. mov esi,[work_palette] ;set the palette
  345. call set_palette
  346. call wait_50hz
  347. pop ecx
  348. loop fade_loop
  349. ; palette is all gone
  350. done: mov al,1
  351. ret
  352. fn_fade_down endp
  353. fn_set_palette proc
  354. ; eax is palette
  355. mov [current_palette],eax
  356. fetch_compact
  357. ; Copy palette to workspace
  358. mov edi,[work_palette]
  359. mov ecx,(3*game_colours)/4
  360. rep movsd
  361. ; and set the palette
  362. mov esi,[work_palette]
  363. call set_palette
  364. mov al,1
  365. ret
  366. fn_set_palette endp
  367. set_palette proc
  368. ; set screen palette
  369. ; palette data pointed to by esi
  370. ; If display in vertical sync wait for next vertical sync
  371. ; If display in display mode wait for vertiacl sync
  372. call get_vsync_flag
  373. jnc not_in_v
  374. call wait_till_out_v_sync
  375. not_in_v: call wait_till_in_v_sync
  376. xor al,al
  377. mov dx,3c8h
  378. out dx,al
  379. inc dx
  380. mov ecx,vga_colours*3/2
  381. fu_tst: lodsb
  382. out dx,al
  383. loop fu_tst
  384. mov al,vga_colours/2
  385. mov dx,3c8h
  386. out dx,al
  387. inc dx
  388. mov ecx,vga_colours*3/2
  389. fu_tst4: lodsb
  390. out dx,al
  391. loop fu_tst4
  392. ret
  393. set_palette endp
  394. halve_palette proc
  395. ; start of the sssss
  396. mov eax,vga_colours*3 ;allocate space for half palette
  397. call my_malloc
  398. mov [half_palette],eax
  399. mov esi,[work_palette]
  400. mov edi,eax
  401. mov ecx,vga_colours*3
  402. half_loop: lodsb
  403. shr al,1
  404. stosb
  405. loop half_loop
  406. mov esi,[half_palette]
  407. call set_palette
  408. ret
  409. halve_palette endp
  410. double_palette proc
  411. mov esi,[work_palette]
  412. call set_palette
  413. mov eax,[half_palette]
  414. call my_free
  415. ret
  416. double_palette endp
  417. clear_screen proc
  418. ; clear front screen
  419. push es
  420. mov es,[screen_segment]
  421. clear eax
  422. clear edi
  423. mov ecx,full_screen_width*full_screen_height/4
  424. rep stosd
  425. pop es
  426. ret
  427. clear_screen endp
  428. wait_till_in_v_sync proc
  429. ; Wait until the display is in a vertical sync, wait while in display mode
  430. ; bit 3 = 0 for display mode
  431. push eax
  432. push edx
  433. llll: call get_vsync_flag
  434. jnc llll
  435. pop edx
  436. pop eax
  437. ret
  438. wait_till_in_v_sync endp
  439. wait_till_out_v_sync proc
  440. ; Wait until the display is in display mode, wait while in a vertical sync
  441. ; bit 3 = 1 for in vertical sync
  442. push eax
  443. push edx
  444. llll: call get_vsync_flag
  445. jc llll
  446. pop edx
  447. pop eax
  448. ret
  449. wait_till_out_v_sync endp
  450. get_vsync_flag proc
  451. ; Get the status of the vertical sync flag
  452. ; bit 3 = 0 for display mode
  453. ; bit 3 = 1 for in vertical sync
  454. mov dx,3dah
  455. in al,dx
  456. bt eax,3
  457. ret
  458. get_vsync_flag endp
  459. frame proc
  460. ; Wait for a full screen frame
  461. call wait_till_out_v_sync
  462. call wait_till_in_v_sync
  463. ret
  464. frame endp
  465. end32code
  466. end
  467.