; BEDLAM v0.2 ; LKS 1995. ; Create: 18\Jun\1995 ; I'm well aware that I don't have a book named after me. ; (Fat and Frantic - Hier soir, ma femme vacuumait ma tete) .MODEL large .STACK 8192 .DATA .CODE .386 ; Segment storage. _zero_seg dw 0000h _psp_seg dw 0000h _code_seg dw 0000h _data_seg dw 0000h _stack_seg dw 0000h _alloc_seg dw 0000h ; 192k allocated (split into 3 x 64k) _scr_seg dw 0000h _sprite_seg dw 0000h _level_seg dw 0000h _text_seg dw 0B800h _graph_seg dw 0A000h ; Memory allocation. _code_size dw 0000h ; Size of shrunk CS. _free_size dw 0000h ; Free memory after shrink. ; Interrupt vectors. _int1C_off dw 0000h ; Old timer interrupt. _int1C_seg dw 0000h _int09_off dw 0000h ; Old keyboard interrupt. _int09_seg dw 0000h ; File handling. _fname db 'BEDLAM.BED ', 00h _handle dw 0000h .STARTUP start: mov _psp_seg, es mov _code_seg, cs mov _data_seg, ds mov _stack_seg, ss call logon call main call logoff .EXIT ;---- LOGON -------------------------------------------------------------------; ;---- Logon. logon: ; 80x50 text mode. mov ax, 3 int 10h mov ax, 1112h xor bx, bx int 10h ; Print logon message. mov es, _text_seg xor di, di call printc db 255, 19h, ' þ ', 255, 1Fh, 'Bedlam v0.2', 255, 19h, ' þ ', 255, 1Fh, ' LKS 1995', 255, 19h, ' þ ', 255, 1Eh, 'Setting up resources.. ', 255, 19h, ' þ ', 00h ; Shrink memory. call print db 0Dh, 0Ah, 0Ah db 'þ Setting up memory', 0Dh, 0Ah, 0Ah db ' Shrinking CS:', 0Dh, 0Ah db ' CS = ', 00h mov cx, 1004h mov dx, cs call printnum call print db 'h', 0Dh, 0Ah, ' Size = ', 00h mov bx, _stack_seg sub bx, _psp_seg mov ax, sp add ax, 15 shr ax, 4 add bx, ax mov cx, 1004h mov _code_size, bx mov dx, bx call printnum call print db 'h', 0Dh, 0Ah, 0Ah, 00h mov ah, 4Ah mov es, _psp_seg int 21h jnc logon_csok call print db 0Dh, 0Ah, 'þ ERROR - Cannot shrink CS.', 0Dh, 0Ah, 00h .EXIT logon_csok: call print db ' Allocating buffers:', 0Dh, 0Ah db ' FreeMem = ', 00h mov ah, 48h mov bx, 0FFFFh int 21h mov _free_size, bx mov cx, 1004h mov dx, _free_size call printnum call print db 'h', 0Dh, 0Ah, 00h cmp _free_size, 3003h jae logon_freememok call print db 0Dh, 0Ah, 'þ ERROR - Cannot allocate 192k buffers.', 0Dh, 0Ah, 00h .EXIT logon_freememok: ; Allocate buffers. mov ah, 48h mov bx, 3000h int 21h mov _alloc_seg, ax mov _scr_seg, ax add ax, 1000h mov _sprite_seg, ax add ax, 1000h mov _level_seg, ax call print db ' ScreenBuf = ', 00h mov cx, 1004h mov dx, _scr_seg call printnum call print db 'h', 0Dh, 0Ah, ' SpriteSeg = ', 00h mov dx, _sprite_seg call printnum call print db 'h', 0Dh, 0Ah, ' LevelSeg = ', 00h mov dx, _level_seg call printnum call print db 'h', 0Dh, 0Ah, 0Ah, 00h ; Load data file. call print db 'þ Loading BEDLAM.BED', 0Dh, 0Ah, 0Ah, 00h ; Open file. mov ax, 3D00h mov dx, offset _fname mov ds, _code_seg int 21h jnc logon_fileok call print db 'þ ERROR - Cannot find default data file.', 0Dh, 0Ah db ' make sure it is in current directory.', 0Dh, 0Ah, 00h .EXIT logon_fileok: mov _handle, ax ; Read palette. mov ah, 3Fh mov bx, _handle mov cx, 768 mov dx, offset _game_pal mov ds, _code_seg int 21h jc logon_read1err cmp ax, 768 jne logon_read1err ; Read sprites. mov ah, 3Fh mov bx, _handle mov cx, 8000h xor dx, dx mov ds, _sprite_seg int 21h jc logon_read1err cmp ax, 8000h je logon_read1ok logon_read1err: call print db 'þ ERROR - Cannot read the sprite data in this file.', 0Dh, 0Ah, 00h .EXIT logon_read1ok: ; Read levels. mov ah, 3Fh mov bx, _handle mov cx, 8000h xor dx, dx mov ds, _level_seg int 21h jc logon_read2err cmp ax, 8000h jne logon_read2err mov ah, 3Fh mov bx, _handle mov cx, 8000h mov dx, 8000h mov ds, _sprite_seg int 21h jc logon_read2err cmp ax, 8000h je logon_read2ok logon_read2err: call print db 'þ ERROR - Cannot read the level data in this file.', 0Dh, 0Ah, 00h .EXIT logon_read2ok: ; Close file mov ah, 3Eh mov bx, _handle int 21h ; Set up interrupt hooks. call print db 'þ Hooking interrupts', 0Dh, 0Ah, 0Ah, 00h mov ax, 351Ch int 21h mov _int1C_off, bx mov _int1C_seg, es mov ax, 3509h int 21h mov _int09_off, bx mov _int09_seg, es call print db ' INT 1Ch - System timer IRQ: OldVect = ', 00h mov cx, 1004h mov dx, _int1C_seg call printnum call print db 'h:', 00h mov dx, _int1C_off call printnum call print db 'h', 0Dh, 0Ah db ' NewVect = ', 00h mov dx, cs call printnum call print db 'h:', 00h mov dx, offset cs: timer call printnum call print db 'h', 0Dh, 0Ah, 0Ah, 00h call print db ' INT 09h - Keyboard IRQ: OldVect = ', 00h mov cx, 1004h mov dx, _int09_seg call printnum call print db 'h:', 00h mov dx, _int09_off call printnum call print db 'h', 0Dh, 0Ah db ' NewVect = ', 00h mov dx, cs call printnum call print db 'h:', 00h mov dx, offset cs: kbd call printnum call print db 'h', 0Dh, 0Ah, 00h ; Pause for keypress. call print db 0Ah, 'þ Press a key..', 00h mov ah, 7 int 21h cmp al, 27 jne logon_notesc call logoff .EXIT logon_notesc: mov ax, 251Ch mov dx, offset cs: timer mov ds, _code_seg int 21h mov ax, 2509h mov dx, offset cs: kbd mov ds, _code_seg int 21h ; Graphics mode. mov ax, 13h int 10h ; Set palette. mov ax, 1012h xor bx, bx mov cx, 256 mov dx, offset cs: _game_pal mov es, _code_seg int 10h ; Sort out sprite masks. mov ds, _sprite_seg xor si, si mov cx, 32000 logon_maskloop: mov al, [si] cmp al, 0 mov al, -1 je logon_maskok mov al, 0 logon_maskok: mov [si+32000], al inc si loop logon_maskloop ; Clear screen buffer. mov es, _scr_seg xor edi, edi mov ecx, 16000 xor eax, eax rep stosd ret ;---- LOGOFF ------------------------------------------------------------------; ;---- Logoff. logoff: ; Free memory mov ah, 29h mov es, _alloc_seg int 21h ; Unhook interrupts. mov ax, 251Ch mov dx, _int1C_off mov ds, _int1C_seg int 21h mov ax, 2509h mov dx, _int09_off mov ds, _int09_seg int 21h ; Clear screen. mov ax, 3 int 10h mov ax, 1112h xor bx, bx int 10h ret ;---- INTERRUPT HANDLERS ------------------------------------------------------; ;---- Int 1Ch _timer_in db 00h _timer_proc dw offset cs: timer_null ; Address of timer procedure. timer: cmp _timer_in, 0 jne timer_end mov _timer_in, 1 push bx mov bx, _timer_proc cmp word ptr cs: [bx], 9090h jne timer_noproc call bx timer_noproc: pop bx mov _timer_in, 0 timer_end: push _int1C_seg push _int1C_off retf ; Null timer proc. timer_null: nop nop ret ;---- Int 09h ; Keyboard IRQ. _kbd_keys db 80h dup (00h) _KBD_ESC equ _kbd_keys[01h] _KBD_UP equ _kbd_keys[48h] _KBD_DOWN equ _kbd_keys[50h] _KBD_LEFT equ _kbd_keys[4Bh] _KBD_RIGHT equ _kbd_keys[4Dh] _KBD_FIRE equ _kbd_keys[36h] _KBD_RSHIFT equ _kbd_keys[36h] _KBD_SPACE equ _kbd_keys[39h] newint09: kbd: push ax push bx ; Store keypress or keyrelease. in al, 60h xor bh, bh mov bl, al test al, 80h jz kbd_press ; Key released. and bl, 7Fh mov _kbd_keys[bx], 0 jmp kbd_after kbd_press: ; Key pressed. mov _kbd_keys[bx], -1 kbd_after: pop bx pop ax cli push ax mov al, 20h out 20h, al pop ax iret ;---- MAIN --------------------------------------------------------------------; ;---- Main. main: call game ret ;---- GAME --------------------------------------------------------------------; _level db 00h _level_curseg dw 0000h _score dd 0000h _player_x db 00h _player_y db 00h _player_off dw 0000h _corner_x db 20 _corner_y db 12 _corner_tx db 00h _corner_ty db 00h _corner_off dw (20)+64*(12) _gameover db 00h _playerok db 00h _dead db 00h _pause db 00h _game_pal db 256 dup (00h, 00h, 00h) _sprite_table dd 01010100h,01010101h,01010101h,01010101h ; Space. dd 0B0A0908h,0F0E0D0Ch,0B0A0908h,0F0E0D0Ch ; Earth. dd 40404040h,40404040H,40404040h,40404040h ; Diamond. dd 4B4B4B4Bh,4F4E4D4Ch,4F4E4D4Ch,4F4E4D4Ch ; Newdia. dd 10101010h,10101010h,10101010h,10101010h ; Bat. dd 18181818h,18181818h,18181818h,18181818h ; Spirit. dd 30313233h,34353637h,30313233h,34353637h ; Rock. dd 20202020h,20202020h,20202020h,20202020h ; Wall. dd 23222120h,27262524h,23222120h,27262524h ; Magic. dd 04030201h,04030201h,04030201h,04030201h ; Bang. dd 2E2E2F2Fh,2C2C2D2Dh,2A2A2B2Bh,28282929h ; Mould. dd 38383838h,38383838h,38383838h,38383838h ; Solid. dd 06060707h,06060707h,06060707h,06060707h ; Door. dd 3B3A3938h,3F3E3D3Ch,3B3A3938h,3F3E3D3Ch ; RSolid. dd 06060606h,07070707h,06060606h,07070707h ; Start. dd 50505050h,50505050h,50505050h,50505050h ; Man. _level_startx db 2 _level_starty db 5 _level_width db 35 _level_height db 28 _level_time db 20 _level_dias db 20 _level_points db 157 _level_flags db 64*64 dup (00h) ;---- Game. game: call game_logon call game_main call game_logoff ret ;---- Game_Logon. game_logon: ; Randomize sozzle buffer. xor bx, bx game_logon_makesozzle: mov cs: _game_sozzle_buf[bx], bl inc bx cmp bx, 240 jne game_logon_makesozzle xor si, si xor bx, bx game_logon_shuffle: in al, 40h add ah, ah xor ah, al sub ah, cs: _game_sozzle_buf[bx] cmp ah, 240 jae game_logon_noshuffle mov bl, ah mov al, cs: _game_sozzle_buf[si] xchg al, cs: _game_sozzle_buf[bx] mov cs: _game_sozzle_buf[si], al game_logon_noshuffle: inc si cmp si, 240 jne game_logon_shuffle ; Set up game variables. mov _level, 1 mov ax, _level_seg mov _score, 0 mov _level_curseg, ax mov _gameover, 0 mov al, _level_startx mov ah, _level_starty mov _player_x, al mov _player_y, ah mov bl, ah xor bh, bh xor ah, ah shl bx, 6 or ax, bx ret ;---- Game_Logoff. game_logoff: ret ;---- Game_Main. game_main: mov _timer_proc, offset cs: game_start game_loop: cmp _KBD_ESC, 0 jne game_end cmp _gameover, 0 je game_loop game_end: ret ;---- GAME TIMER PROCEDURES. _game_sozzle_buf db 240 dup (00h) _game_sozzle_frame db 00h _game_sozzle_block db 0D0h ;---- Game_Start. ; The start of the game loop. game_start: nop nop mov _game_sozzle_frame, 0 mov _timer_proc, offset cs: game_start_proc game_start_proc: nop nop call game_sozzleframe call game_status call update add _game_sozzle_frame, 5 cmp _game_sozzle_frame, 240 jna game_start_ok mov _game_sozzle_frame, 255 mov _timer_proc, offset cs: game_play game_start_ok: ret ;---- Game_Play. ; Moves the game on a frame. _game_play_time db 00h _game_play_bar db 00h game_play: nop nop inc _game_play_time cmp _game_play_time, 18 jb game_play_timeok mov _game_play_time, 0 dec _level_time inc _game_play_bar game_play_timeok: call game_move call game_frame ; Print status or message. cmp _playerok, 0 jne game_play_status cmp _KBD_SPACE, 0 je game_play_lifeoverok mov _timer_proc, offset cs: game_finish game_play_lifeoverok: test _game_play_bar, 2 jz game_play_status call game_pressspace jmp game_play_nostatus game_play_status: call game_status game_play_nostatus: call update ret ;---- Game_Finish. _game_finish_pause db 00h game_finish: nop nop mov _game_sozzle_frame, 240 mov _timer_proc, offset cs: game_finish_proc mov _game_finish_pause, 18*2 game_finish_proc: nop nop call game_sozzleframe call game_status call update sub _game_sozzle_frame, 5 cmp _game_sozzle_frame, 4 ja game_finish_ok mov _game_sozzle_frame, 0 mov _timer_proc, offset cs: game_finish_pause game_finish_ok: ret game_finish_pause: nop nop call game_sozzleframe call game_status call update dec _game_finish_pause jnz game_finish_pause_ok mov _timer_proc, offset cs: game_start mov _corner_x, 20 mov _corner_y, 12 mov _corner_tx, 00h mov _corner_ty, 00h mov _corner_off, (20)+64*(12) game_finish_pause_ok: ret ;---- GAME MISC ROUTINNES. game_move: push ds push es push eax push ecx push dx push si push edi ; Clear moved flags. mov es, _code_seg xor edi, edi xor ecx, ecx mov di, offset cs: _level_flags mov cx, 64*64/4 xor eax, eax rep stosd mov _playerok, 0 ; Move each character in turn. mov ds, _level_curseg xor si, si mov dh, 64 game_move_y: mov dl, 64 game_move_x: cmp _level_flags[si], 0 jne game_move_no mov al, [si] cmp al, 10h jb move_space_ cmp al, 20h jb move_earth_ cmp al, 30h jb move_diamond_ cmp al, 40h jb move_newdia_ cmp al, 50h jb move_bat_ cmp al, 60h jb move_spirit_ cmp al, 70h jb move_rock_ cmp al, 80h jb move_wall_ cmp al, 90h jb move_magic_ cmp al, 0A0h jb move_bang_ cmp al, 0B0h jb move_mould_ cmp al, 0C0h jb move_solid_ cmp al, 0D0h jb move_door_ cmp al, 0E0h jb move_rsolid_ cmp al, 0F0h jb move_start_ jmp move_man_ game_move_ok: game_move_no: inc si dec dl jnz game_move_x dec dh jnz game_move_y pop edi pop si pop dx pop ecx pop eax pop es pop ds ret ;---- Individual move routines. ; Branches. move_space_: jmp move_space move_earth_: jmp move_earth move_diamond_: jmp move_diamond move_newdia_: jmp move_newdia move_bat_: jmp move_bat move_spirit_: jmp move_spirit move_rock_: jmp move_rock move_wall_: jmp move_wall move_magic_: jmp move_magic move_bang_: jmp move_bang move_mould_: jmp move_mould move_solid_: jmp move_solid move_door_: jmp move_door move_rsolid_: jmp move_rsolid move_start_: jmp move_start move_man_: jmp move_man ; These characters don't seem to do much. move_space: move_earth: move_wall: move_solid: move_rsolid: jmp game_move_ok ; Characters not yet programmed. move_door: move_magic: move_mould: jmp game_move_ok ; Move newdia. move_newdia: mov byte ptr [si], 20h jmp game_move_ok push ax mov al, [si] inc al and al, 3 jz move_newdia_diamond or al, 30h mov [si], al pop ax jmp game_move_ok move_newdia_diamond: mov byte ptr [si], 20h pop ax jmp game_move_ok ; Move bang. move_bang: push ax mov al, [si] mov ah, al inc al and ah, 0FCh and al, 3 jz move_bang_gone or al, ah mov [si], al pop ax jmp game_move_ok move_bang_gone: cmp ah, 9Ch je move_bang_man mov byte ptr [si], 0 pop ax jmp game_move_ok move_bang_man: mov byte ptr [si], 0F0h pop ax jmp game_move_ok ; Move start. move_start: push ax mov al, [si] inc al and al, 0Fh or al, 0E0h cmp al, 0E0h jne move_start_ok mov al, 9Ch move_start_ok: mov [si], al pop ax jmp game_move_ok ; Move fallers. move_diamond: move_rock: push ax push di ; Is there a gap below? test byte ptr [si+64], 0F0h jnz move_rock_nofall lea di, [si+64] jmp move_rock_move move_rock_nofall: mov ah, [si+64] and ah, 0F0h cmp ah, 20h je move_rock_slip cmp ah, 60h je move_rock_slip cmp ah, 70h je move_rock_slip cmp ah, 0A0h je move_rock_slip jmp move_rock_noslip move_rock_slip: test byte ptr [si+1], 0F0h jnz move_rock_noright test byte ptr [si+65], 0F0h jnz move_rock_noright lea di, [si+1] jmp move_rock_move move_rock_noright: test byte ptr [si-1], 0F0h jnz move_rock_noleft test byte ptr [si+63], 0F0h jnz move_rock_noleft lea di, [si-1] jmp move_rock_move move_rock_noleft: move_rock_noslip: and byte ptr [si], 0F7h pop di pop ax jmp game_move_ok move_rock_move: cmp si, di je move_rock_end or byte ptr [si], 8 test al, 8 jz move_rock_end or al, 8 mov byte ptr [si], 0 mov [di], al mov _level_flags[di], 8 ; Check for hits if falling (not slipping). sub di, 64 cmp di, si jne move_rock_end mov ah, [si+128] and ah, 0F0h cmp ah, 40h je move_rock_hitbat cmp ah, 50h je move_rock_hitspirit cmp ah, 0F0h je move_rock_hitman move_rock_end: pop di pop ax jmp game_move_ok move_rock_hitbat: mov ah, 30h lea di, [si+128] call move_detonate jmp move_rock_end move_rock_hitspirit: move_rock_hitman: mov ah, 90h lea di, [si+128] call move_detonate jmp move_rock_end ; Move bat. _bat_dir dw -64, 1, 64, -1, -64, 1, 64, -1 move_bat: push ax push bx push di mov bl, al and bl, 03h xor bh, bh add bl, bl ; Is there anything to it's left (relative to it's direction)? mov di, si add di, _bat_dir[bx+6] test byte ptr [di], 0F0h jnz move_bat_notleft ; If there is nothing left, go that way. mov bl, al mov ah, al add bl, 3 and ah, 0F0h and bl, 3 mov byte ptr [si], 0 or ah, bl mov _level_flags[di], 1 mov [di], ah jmp move_bat_touch move_bat_notleft: ; There is something on the left to follow round. ; Check if there is anything forward. mov di, si add di, _bat_dir[bx] test byte ptr ds: [di], 0F0h jnz move_bat_noforward mov byte ptr [si], 0 mov _level_flags[di], 1 mov [di], al jmp move_bat_touch move_bat_noforward: ; Forward blocked so turn right. mov di, si add di, _bat_dir[bx+2] mov bl, al mov ah, al inc bl and ah, 0F0h and bl, 3 or ah, bl mov [si], ah move_bat_touch: mov ah, [si-64] and ah, 0F0h cmp ah, 0A0h je move_bat_detonate cmp ah, 0F0h je move_bat_detonate mov ah, [si+64] and ah, 0F0h cmp ah, 0A0h je move_bat_detonate cmp ah, 0F0h je move_bat_detonate mov ah, [si-1] and ah, 0F0h cmp ah, 0A0h je move_bat_detonate cmp ah, 0F0h je move_bat_detonate mov ah, [si+1] and ah, 0F0h cmp ah, 0A0h je move_bat_detonate cmp ah, 0F0h je move_bat_detonate pop di pop bx pop ax jmp game_move_ok move_bat_detonate: mov ah, 30h mov di, si call move_detonate pop di pop bx pop ax jmp game_move_ok ; Move spirit. _spirit_dir dw 64, 1, -64, -1, 64, 1, -64, -1 move_spirit: push ax push bx push di mov bl, al and bl, 03h xor bh, bh add bl, bl ; Is there anything to it's left (relative to it's direction)? mov di, si add di, _spirit_dir[bx+6] test byte ptr [di], 0F0h jnz move_spirit_notleft ; If there is nothing left, go that way. mov bl, al mov ah, al add bl, 3 and ah, 0F0h and bl, 3 mov byte ptr [si], 0 or ah, bl mov _level_flags[di], 1 mov [di], ah jmp move_spirit_touch move_spirit_notleft: ; There is something on the left to follow round. ; Check if there is anything forward. mov di, si add di, _spirit_dir[bx] test byte ptr ds: [di], 0F0h jnz move_spirit_noforward mov byte ptr [si], 0 mov _level_flags[di], 1 mov [di], al jmp move_spirit_touch move_spirit_noforward: ; Forward blocked so turn right. mov di, si add di, _spirit_dir[bx+2] mov bl, al mov ah, al inc bl and ah, 0F0h and bl, 3 or ah, bl mov [si], ah move_spirit_touch: mov ah, [si-64] and ah, 0F0h cmp ah, 0A0h je move_spirit_detonate cmp ah, 0F0h je move_spirit_detonate mov ah, [si+64] and ah, 0F0h cmp ah, 0A0h je move_spirit_detonate cmp ah, 0F0h je move_spirit_detonate mov ah, [si-1] and ah, 0F0h cmp ah, 0A0h je move_spirit_detonate cmp ah, 0F0h je move_spirit_detonate mov ah, [si+1] and ah, 0F0h cmp ah, 0A0h je move_spirit_detonate cmp ah, 0F0h je move_spirit_detonate pop di pop bx pop ax jmp game_move_ok move_spirit_detonate: mov ah, 90h mov di, si call move_detonate pop di pop bx pop ax jmp game_move_ok ; Move man. _move_man_left db 58h, 59h, 5Ah, 5Bh, 5Ch, 5Dh, 5Bh, 5Ah, 59h, -1 _move_man_right db 60h, 61h, 62h, 63h, 64h, 65h, 64h, 63h, 62h, -1 _move_man_ptr dw offset _move_man_right _move_man_dir dw offset _move_man_right _move_man_push db 00h move_man: push ax mov _playerok, 1 mov _game_play_bar, 0 inc _move_man_push and _move_man_push, 0Fh mov byte ptr [si], 0F0h ; Up? xor al, al cmp _KBD_UP, 0 je move_man_noup mov byte ptr [si], 0F1h cmp byte ptr [si-64], 30h jnb move_man_noup mov al, [si-64] mov cs: _game_man_frame, offset cs: _game_man_anim cmp _KBD_FIRE, 0 je move_man_up_nofire mov byte ptr [si-64], 90h mov _level_flags[si-64], 1 jmp move_man_after move_man_up_nofire: dec _player_y sub _player_off, 64 mov byte ptr [si], 0 mov byte ptr [si-64], 0F1h mov _level_flags[si-64], 1 jmp move_man_after move_man_noup: ; Down? cmp _KBD_DOWN, 0 je move_man_nodown mov byte ptr [si], 0F1h cmp byte ptr [si+64], 30h jnb move_man_nodown mov al, [si+64] mov cs: _game_man_frame, offset cs: _game_man_anim cmp _KBD_FIRE, 0 je move_man_down_nofire mov byte ptr [si+64], 90h mov _level_flags[si+64], 1 jmp move_man_after move_man_down_nofire: inc _player_y add _player_off, 64 mov byte ptr [si], 0 mov byte ptr [si+64], 0F1h mov _level_flags[si+64], 1 jmp move_man_after move_man_nodown: ; Left? cmp _KBD_LEFT, 0 je move_man_noleft mov byte ptr [si], 0F1h cmp _move_man_dir, offset _move_man_left je move_man_leftok mov _move_man_dir, offset _move_man_left mov _move_man_ptr, offset _move_man_left move_man_leftok: mov ah, [si-1] and ah, 0F0h cmp ah, 60h jne move_man_noleftpush cmp _move_man_push, 0 jne move_man_noleftpush test byte ptr [si-2], 0F0h jnz move_man_noleftpush mov ah, [si-1] mov [si-2], ah mov byte ptr [si-1], 0 move_man_noleftpush: cmp byte ptr [si-1], 30h jnb move_man_noleft mov al, [si-1] mov cs: _game_man_frame, offset cs: _game_man_anim cmp _KBD_FIRE, 0 je move_man_left_nofire mov byte ptr [si-1], 90h mov _level_flags[si-1], 1 jmp move_man_after move_man_left_nofire: dec _player_x dec _player_off mov byte ptr [si], 0 mov byte ptr [si-1], 0F1h mov _level_flags[si-1], 1 jmp move_man_after move_man_noleft: ; Right? cmp _KBD_RIGHT, 0 je move_man_noright mov ah, [si+1] and ah, 0F0h cmp ah, 60h jne move_man_norightpush cmp _move_man_push, 0 jne move_man_norightpush test byte ptr [si+2], 0F0h jnz move_man_norightpush mov ah, [si+1] mov [si+2], ah mov byte ptr [si+1], 0 move_man_norightpush: mov byte ptr [si], 0F1h cmp _move_man_dir, offset _move_man_right je move_man_rightok mov _move_man_dir, offset _move_man_right mov _move_man_ptr, offset _move_man_right move_man_rightok: cmp byte ptr [si+1], 30h jnb move_man_noright mov al, [si+1] mov cs: _game_man_frame, offset cs: _game_man_anim cmp _KBD_FIRE, 0 je move_man_right_nofire mov byte ptr [si+1], 90h mov _level_flags[si+1], 1 jmp move_man_after move_man_right_nofire: inc _player_x inc _player_off mov byte ptr [si], 0 mov byte ptr [si+1], 0F1h mov _level_flags[si+1], 1 jmp move_man_after move_man_noright: move_man_after: and al, 0F0h cmp al, 20h jne move_man_notdia xor ah, ah mov al, _level_points add word ptr _score, ax adc word ptr _score[4], 0 cmp _level_dias, 0 je move_man_notdia dec _level_dias move_man_notdia: pop ax jmp game_move_ok ;---- Move_Detonate. move_detonate: push di sub di, 65 call move_detonate_put inc di call move_detonate_put inc di call move_detonate_put add di, 62 call move_detonate_put inc di call move_detonate_put inc di call move_detonate_put add di, 62 call move_detonate_put inc di call move_detonate_put inc di call move_detonate_put pop di ret move_detonate_put: cmp byte ptr [di], 0B0h je move_detonate_put_end cmp byte ptr [di], 0D0h je move_detonate_put_end mov [di], ah mov _level_flags[di], 1 move_detonate_put_end: ret ;---- BEDLAM GRAPHICS ROUTINES ------------------------------------------------; ;---- Game_Rotate _game_man_anim db 36 dup (50h), 51h, 52h, 53h, 52h, 51h db 4 dup (50h, 50h, 54h, 54h), 9 dup (55h) db 6 dup (50h), 4 dup (55h) db 4 dup (50h, 50h, 54h, 54h), 51h, 52h, 53h, 52h, 51h, 50h db -1 _game_man_frame dw offset _game_man_anim ; Rotate sprites. game_rotate: push ax push bx ; Man. mov bx, _game_man_frame mov al, cs: [bx] inc bx cmp al, -1 jne game_rotate_manok mov bx, offset cs: _game_man_anim mov al, cs: [bx] game_rotate_manok: mov _game_man_frame, bx mov byte ptr _sprite_table[0F0h], al mov bx, _move_man_ptr mov al, cs: [bx] inc bx cmp al, -1 jne move_man_frameok mov bx, _move_man_dir mov al, cs: [bx] move_man_frameok: mov _move_man_ptr, bx mov byte ptr _sprite_table[0F1h], al ; Diamond. mov al, byte ptr _sprite_table[20h] mov bx, 20h inc al cmp al, 4Ah jna game_rotate_diaok mov al, 40h game_rotate_diaok: mov ah, al call game_rotate_put ; Others. mov ah, 10h mov bx, 40h call game_rotate_one mov ah, 18h mov bx, 50h call game_rotate_one mov ah, 20h mov bx, 80h call game_rotate_one mov ah, 38h mov bx, 0D0h call game_rotate_one pop bx pop ax ret game_rotate_one: mov al, byte ptr _sprite_table[bx] inc al and al, 7 or al, ah mov ah, al game_rotate_put: mov word ptr _sprite_table[bx], ax mov word ptr _sprite_table[bx+2], ax mov word ptr _sprite_table[bx+4], ax mov word ptr _sprite_table[bx+6], ax mov word ptr _sprite_table[bx+8], ax mov word ptr _sprite_table[bx+10], ax mov word ptr _sprite_table[bx+12], ax mov word ptr _sprite_table[bx+14], ax ret ;---- Game_Scroll. game_scroll: push ax ; Horizontal movement. mov al, _corner_x cmp al, _corner_tx je game_scroll_nohoriz jl game_scroll_right cmp _corner_x, 0 je game_scroll_nohoriz dec _corner_x dec _corner_off call game_back_left jmp game_scroll_nohoriz game_scroll_right: mov ah, _level_width sub ah, 20 cmp _corner_x, ah jge game_scroll_nohoriz inc _corner_x inc _corner_off call game_back_right game_scroll_nohoriz: ; Vertical movement. mov al, _corner_y cmp al, _corner_ty je game_scroll_novert jl game_scroll_down cmp _corner_y, 0 je game_scroll_novert dec _corner_y sub _corner_off, 64 call game_back_up jmp game_scroll_novert game_scroll_down: mov ah, _level_height sub ah, 12 cmp _corner_y, ah jge game_scroll_novert inc _corner_y add _corner_off, 64 call game_back_down game_scroll_novert: ; Scroll if necessary. mov al, _player_x sub al, _corner_x cmp al, 4 jl game_scroll_manleft cmp al, 14 jl game_scroll_afterhoriz mov al, _player_x sub al, 9 mov _corner_tx, al jmp game_scroll_afterhoriz game_scroll_manleft: mov al, _player_x sub al, 8 mov _corner_tx, al game_scroll_afterhoriz: mov al, _player_y sub al, _corner_y cmp al, 4 jl game_scroll_manup cmp al, 8 jl game_scroll_aftervert mov al, _player_y sub al, 5 mov _corner_ty, al jmp game_scroll_aftervert game_scroll_manup: mov al, _player_y sub al, 6 mov _corner_ty, al game_scroll_aftervert: pop ax ret game_back_up: push ds push es push cx push si push di mov ds, _code_seg mov es, _code_seg cld mov cx, 32 mov si, offset cs: _game_back_data + 32*31 mov di, offset cs: _game_back_data + 32*32 game_back_up_loop: push cx mov cx, 16 rep movsw pop cx sub si, 64 sub di, 64 loop game_back_up_loop mov si, offset cs: _game_back_data + 32*32 mov di, offset cs: _game_back_data mov cx, 16 rep movsw pop di pop si pop cx pop es pop ds ret game_back_down: push ds push es push cx push si push di mov ds, _code_seg mov es, _code_seg cld mov si, offset cs: _game_back_data mov di, offset cs: _game_back_data + 32*32 mov cx, 16 rep movsw mov cx, 32 mov si, offset cs: _game_back_data + 32 mov di, offset cs: _game_back_data game_back_down_loop: push cx mov cx, 16 rep movsw pop cx loop game_back_down_loop pop di pop si pop cx pop es pop ds ret game_back_right: push ds push es push cx push si push di cld mov ds, _code_seg mov es, _code_seg mov si, offset cs: _game_back_data mov di, offset cs: _game_back_data mov cx, 32 game_back_right_loop: push cx lodsb mov cx, 31 rep movsb stosb pop cx loop game_back_right_loop pop di pop si pop cx pop es pop ds ret game_back_left: push ds push es push cx push si push di cld mov ds, _code_seg mov es, _code_seg mov si, offset cs: _game_back_data+31 mov cx, 32 game_back_left_loop: push cx mov ch, [si] mov cl, 31 game_back_left_xloop: mov al, [si-1] mov [si], al dec si dec cl jnz game_back_left_xloop mov [si], ch add si, 63 pop cx loop game_back_left_loop pop di pop si pop cx pop es pop ds ret ;---- Game_SozzleFrame. game_sozzleframe: push es push ds push ax push bx push dx push si push di call game_scroll ; Rotate animated sprites. call game_rotate mov ds, _level_seg mov es, _scr_seg call game_back xor bx, bx mov dh, 12 mov si, _corner_off mov di, 0 game_sozzleframe_ysozzle: mov dl, 20 push di game_sozzleframe_xsozzle: mov al, _game_sozzle_buf[bx] cmp al, _game_sozzle_frame jae game_sozzleframe_block mov al, [si] call blit jmp game_sozzleframe_next game_sozzleframe_block: mov al, _game_sozzle_block call blit game_sozzleframe_next: inc bx inc si add di, 16 dec dl jnz game_sozzleframe_xsozzle pop di add di, 320*16 add si, 64-20 dec dh jnz game_sozzleframe_ysozzle inc _game_sozzle_block and _game_sozzle_block, 7 or _game_sozzle_block, 0D0h pop di pop si pop dx pop bx pop ax pop ds pop es ret ;---- Game_Frame. game_frame: push es push ds push ax push bx push dx push si push di call game_scroll ; Rotate animated sprites. call game_rotate mov ds, _level_seg mov es, _scr_seg call game_back xor bx, bx mov dh, 12 mov si, _corner_off mov di, 0 game_frame_y: mov dl, 20 push si push di game_frame_x: mov al, [si] call blit inc bx inc si add di, 16 dec dl jnz game_frame_x pop di pop si add di, 320*16 add si, 64 dec dh jnz game_frame_y pop di pop si pop dx pop bx pop ax pop ds pop es ret ;---- Game_Back. _game_back_data dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 01C1C1C1Ch, 01D1D1D1Ch, 01D1D1D1Dh, 01C1C1C1Ch dd 01C1C1C1Ch, 01C1C1C1Ch, 01C1C1C1Ch, 01C1C1C1Ch dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01F1D1D1Dh, 01D1D1D1Eh, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01F1D1Dh, 01D1D1C00h, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01E1D1Dh, 01D1D1B00h, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01C1D1D1Dh, 01D1D1D1Bh, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh, 01D1D1D1Dh dd 01E1E1E1Eh, 01D1D1D1Dh, 01E1D1D1Dh, 01E1E1E1Eh dd 01E1E1E1Eh, 01E1E1E1Eh, 01E1E1E1Eh, 01E1E1E1Eh dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 00h, 01D1D1D1Ch, 01E1D1D1Dh, 00h dd 00h, 00h, 00h, 00h dd 8 dup (00000000h) game_back: push ds push ax push cx push dx push esi push edi cld mov ds, _code_seg xor esi, esi xor edi, edi mov dh, 6 game_back_yloop: push di mov dl, 10 game_back_xloop: mov si, offset cs: _game_back_data push di mov al, 32 game_back_yblit: mov cx, 8 rep movsd add di, 320-32 dec al jnz game_back_yblit pop di add di, 32 dec dl jnz game_back_xloop pop di add di, 320*32 dec dh jnz game_back_yloop pop edi pop esi pop dx pop cx pop ax pop ds ret ;---- Game_Status. _game_digits dd 0FFFFFF00h, 0FFFFh, 0FFh, 0FF0000h dd 0FFh, 0FFFF00h, 0FFh, 0FF00FFh dd 0FF0000FFh, 0FF0000h, 0FF00FFh, 0FF0000h dd 0FFFFh, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 00h, 00h dd 0FF000000h, 00h, 0FFFF0000h, 00h dd 0FF00FF00h, 00h, 0FF0000FFh, 00h dd 0FF000000h, 00h, 0FF000000h, 00h dd 0FF000000h, 00h, 0FF000000h, 00h dd 0FFFFFFFFh, 0FFFFFFh, 00h, 00h dd 0FFFFFF00h, 0FFFFh, 0FFh, 0FF0000h dd 00h, 0FF0000h, 00h, 0FF00h dd 00h, 0FFh, 0FF000000h, 00h dd 0FF0000h, 00h, 0FF00h, 00h dd 0FFFFFFFFh, 0FFFFFFh, 00h, 00h dd 0FFFFFFFFh, 0FFFFFFh, 00h, 0FF00h dd 00h, 0FFh, 0FF000000h, 00h dd 00h, 0FFh, 00h, 0FF00h dd 00h, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 00h, 00h dd 00h, 0FF00h, 00h, 0FFFFh dd 0FF000000h, 0FF00h, 0FF0000h, 0FF00h dd 0FF00h, 0FF00h, 0FFFFFFFFh, 0FFFFFFh dd 00h, 0FF00h, 00h, 0FF00h dd 00h, 0FF00h, 00h, 00h dd 0FFFFFFFFh, 0FFFFFFh, 0FFh, 00h dd 0FFh, 00h, 0FFFFFFFFh, 0FFFFh dd 00h, 0FF0000h, 00h, 0FF0000h dd 00h, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 00h, 00h dd 0FFFFFF00h, 0FFFFh, 0FFh, 0FF0000h dd 0FFh, 00h, 0FFFFFFFFh, 0FFFFh dd 0FFh, 0FF0000h, 0FFh, 0FF0000h dd 0FFh, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 00h, 00h dd 0FFFFFFFFh, 0FFFFFFh, 00h, 0FF0000h dd 00h, 0FF0000h, 00h, 0FF00h dd 00h, 0FFh, 0FF000000h, 00h dd 0FF000000h, 00h, 0FF000000h, 00h dd 0FF000000h, 00h, 00h, 00h dd 0FFFFFF00h, 0FFFFh, 0FFh, 0FF0000h dd 0FFh, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 0FFh, 0FF0000h dd 0FFh, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 00h, 00h dd 0FFFFFF00h, 0FFFFh, 0FFh, 0FF0000h dd 0FFh, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFFFh, 00h, 0FF0000h dd 00h, 0FF0000h, 0FFh, 0FF0000h dd 0FFFFFF00h, 0FFFFh, 00h, 00h dd 00h, 049h, 048000000h, 049B9h dd 034470000h, 04A0D23h, 048484700h, 04B0D2334h dd 068687948h, 023344857h, 087874900h, 04B576879h dd 0944A0000h, 04B7987h, 04B000000h, 04BA8h dd 00h, 04Ah, 00h, 00h dd 0FFFFFF00h, 0FFFFFFh, 0FF00h, 0FF000000h dd 0FF00h, 0FF000000h, 0FF00h, 0FF000000h dd 0FFFFFF00h, 0FFFFFFh, 0FF00h, 00h dd 0FF00h, 00h, 0FF00h, 00h dd 0FF00h, 00h, 00h, 00h dd 0FFFFFF00h, 0FFFFFFh, 0FF00h, 0FF000000h dd 0FF00h, 0FF000000h, 0FF00h, 0FF000000h dd 0FFFFFF00h, 0FFFFFFh, 0FF00h, 0FFh dd 0FF00h, 0FF00h, 0FF00h, 0FF0000h dd 0FF00h, 0FF000000h, 00h, 00h dd 0FFFFFF00h, 0FFFFFFFFh, 0FF00h, 00h dd 0FF00h, 00h, 0FF00h, 00h dd 0FFFFFF00h, 0FFFFFFh, 0FF00h, 00h dd 0FF00h, 00h, 0FF00h, 00h dd 0FFFFFF00h, 0FFFFFFFFh, 00h, 00h dd 0FFFF0000h, 0FFFFFFh, 0FF00h, 0FF000000h dd 0FF00h, 00h, 0FF00h, 00h dd 0FFFF0000h, 0FFFFFFh, 00h, 0FF000000h dd 00h, 0FF000000h, 0FF00h, 0FF000000h dd 0FFFF0000h, 0FFFFFFh, 00h, 00h dd 00h, 00h, 00h, 00h dd 00h, 00h, 00h, 00h dd 00h, 00h, 00h, 00h dd 00h, 00h, 00h, 00h dd 00h, 00h, 00h, 00h dd 0FFFF0000h, 0FFFFFFh, 0FF00h, 0FF000000h dd 0FF00h, 0FF000000h, 0FF00h, 0FF000000h dd 0FFFFFF00h, 0FFFFFFFFh, 0FF00h, 0FF000000h dd 0FF00h, 0FF000000h, 0FF00h, 0FF000000h dd 0FF00h, 0FF000000h, 00h, 00h dd 0FFFF0000h, 0FFFFFFh, 0FF00h, 0FF000000h dd 0FF00h, 00h, 0FF00h, 00h dd 0FF00h, 00h, 0FF00h, 00h dd 0FF00h, 00h, 0FF00h, 0FF000000h dd 0FFFF0000h, 0FFFFFFh, 00h, 00h game_status: push es push eax push cx push edx push ebx push si push di mov es, _scr_seg mov di, 64000-8*320 mov cx, 320*8/2 xor ax, ax rep stosw mov di, (160-18*8/2)+190*320 ; Score per diamond. mov al, _level_points call game_3digit ; Diamond icon. mov al, 10 call game_digit mov byte ptr es: [di+323], 0 mov byte ptr es: [di+325], 0 mov byte ptr es: [di+4], 0 mov al, byte ptr es: [di+7+4*320] mov byte ptr es: [di+8+5*320], al add di, 10 ; Number of diamonds left. mov al, _level_dias call game_3digit ; Score. mov eax, _score mov ebx, 10 mov cx, 6 game_status_scorecalc: xor edx, edx div ebx push dx loop game_status_scorecalc mov cx, 6 game_status_scoreblit: pop ax add di, 8 call game_digit loop game_status_scoreblit add di, 8 ; Time. add di, 8 mov al, _level_time call game_3digit pop di pop si pop ebx pop edx pop cx pop eax pop es ret game_3digit: mov dl, 10 xor ah, ah div dl push ax xor ah, ah div dl push ax xor ah, ah div dl mov al, ah call game_digit add di, 8 pop ax mov al, ah call game_digit add di, 8 pop ax mov al, ah call game_digit add di, 8 ret game_pressspace: push es push ax push cx push di mov es, _scr_seg mov di, 64000-8*320 mov cx, 320*8/2 xor ax, ax rep stosw mov di, (160-18*8/2)+190*320 mov di, (160-11*8/2)+190*320 mov al, 11 call game_digit add di, 8 mov al, 12 call game_digit add di, 8 mov al, 13 call game_digit add di, 8 mov al, 14 call game_digit add di, 8 mov al, 14 call game_digit add di, 8 mov al, 15 call game_digit add di, 8 mov al, 14 call game_digit add di, 8 mov al, 11 call game_digit add di, 8 mov al, 16 call game_digit add di, 8 mov al, 17 call game_digit add di, 8 mov al, 13 call game_digit pop di pop cx pop ax pop es ret game_digit: push eax push cx push dx push ebx push si push di mov dx, 80 xor ah, ah mul dx mov si, ax add si, offset _game_digits ; Shadow. mov eax, cs: [si] mov ebx, cs: [si+4] not eax not ebx and es: [di], eax and es: [di+4], ebx mov eax, cs: [si+8] mov ebx, cs: [si+12] not eax not ebx and es: [di+320], eax and es: [di+324], ebx ; Digit. mov cx, 10 game_digit_loop: mov eax, cs: [si] mov ebx, cs: [si+4] or es: [di+320], eax or es: [di+324], ebx add si, 8 add di, 320 loop game_digit_loop pop di pop si pop ebx pop dx pop cx pop eax ret ;---- Update. ; Copies SCR_SEG onto screen. update: push ds push es push ecx push esi push edi mov ds, _scr_seg mov es, _graph_seg xor esi, esi xor edi, edi mov ecx, 16000 cld rep movsd pop edi pop esi pop ecx pop es pop ds ret ;---- Blit. ; AL - Character. ; ES:DI - Destination. blit: push ds push es push eax push ebx push cx push si push di ; Convert character to sprite number then to offset. xor ah, ah mov si, ax mov ah, byte ptr _sprite_table[si] xor al, al mov si, ax ; Blit sprite. mov ds, _sprite_seg mov es, _scr_seg mov ah, al mov cx, 16 blit_loop: ; AND mask. mov eax, [si+32000] mov ebx, [si+32004] and es: [di], eax and es: [di+4], ebx mov eax, [si+32008] mov ebx, [si+32012] and es: [di+8], eax and es: [di+12], ebx ; XOR mask. mov eax, [si] mov ebx, [si+4] xor es: [di], eax xor es: [di+4], ebx mov eax, [si+8] mov ebx, [si+12] xor es: [di+8], eax xor es: [di+12], ebx add si, 16 add di, 320 loop blit_loop pop di pop si pop cx pop ebx pop eax pop es pop ds ret ;---- LIBRARY ROUTINES v0.2 ---------------------------------------------------; ;---- GetKey ; Returns key pressed in AL, or zero in AL and scan code in AH or zero in AX if ; no key in buffer. getkey: mov ah, 0Bh int 21h cmp al, 0FFh je getkey_get xor ax, ax ret getkey_get: mov ah, 7 int 21h cmp al, 0 je getkey_ext xor ah, ah ret getkey_ext: mov ah, 7 int 21h mov ah, al xor al, al ret ;---- PrintC ; AH = attribute ; CS:IP = string ; ES:DI = destination _printc_si dw 0000h printc: mov _printc_si, si pop si push ax printc_loop: mov al, cs: [si] inc si or al, al je printc_end cmp al, 255 jne printc_notattr mov ah, cs: [si] inc si jmp printc_loop printc_notattr: stosw jmp printc_loop printc_end: pop ax push si mov si, _printc_si ret ;---- Print ; CS:IP = text. _print_si dw 0000h print: mov _print_si, si pop si push ax print_loop: mov al, cs: [si] inc si or al, al je print_end int 29h jmp print_loop print_end: pop ax push si mov si, _print_si ret ;---- PrintNumC ; AH = attribute ; CH = base ; CL = digits ; EDX = Number ; ES:DI = destination _printnumc_table db '0123456789ABCDEF' _printnumc_attr db 00h _printnumc_len db 00h _printnumc_base db 00h printnumc: ; Valiate input. cmp ch, 0 je printnumc_end cmp ch, 16 ja printnumc_end cmp cl, 0 je printnumc_end cmp cl, 8 ja printnumc_end push eax push ecx push edx push ebx mov _printnumc_attr, ah mov _printnumc_len, cl mov _printnumc_base, ch xor ch, ch mov eax, edx printnumc_calc: xor ebx, ebx mov bl, _printnumc_base xor edx, edx div ebx xor bh, bh mov bl, dl mov dh, _printnumc_attr mov dl, _printnumc_table[bx] push dx loop printnumc_calc mov cl, _printnumc_len printnumc_print: pop ax stosw loop printnumc_print pop ebx pop edx pop ecx pop eax printnumc_end: ret ;---- PrintNum ; CH = base ; CL = digits ; EDX = Number _printnum_table db '0123456789ABCDEF' _printnum_len db 00h _printnum_base db 00h printnum: ; Valiate input. cmp ch, 0 je printnum_end cmp ch, 16 ja printnum_end cmp cl, 0 je printnum_end cmp cl, 8 ja printnum_end push eax push ecx push edx push ebx mov _printnum_len, cl mov _printnum_base, ch xor ch, ch mov eax, edx printnum_calc: xor ebx, ebx mov bl, _printnum_base xor edx, edx div ebx xor bh, bh mov bl, dl xor dh, dh mov dl, _printnum_table[bx] push dx loop printnum_calc mov cl, _printnum_len printnum_print: pop ax int 29h loop printnum_print pop ebx pop edx pop ecx pop eax printnum_end: ret ;---- END OF CODE -------------------------------------------------------------; END