mirror of
https://github.com/ScrelliCopter/TECHNO.COM.git
synced 2025-02-21 01:59:25 +11:00
add disassemblies
This commit is contained in:
288
disassembly/technom.asm
Normal file
288
disassembly/technom.asm
Normal file
@@ -0,0 +1,288 @@
|
||||
; TECHNO.COM (payload only) Disassembly by a dinosaur 2022, 2024 (original author unknown)
|
||||
; Binary MD5: 4CB859537BCD7BFB9FC5BFD6D74F4782
|
||||
; SHA256: BA33A41BA51C3D56B27107A94EF7842235B6D80A3A5B8710AEBDD87EB3A1905C
|
||||
;
|
||||
; Assemble with Microsoft Macro Assembler: ml.exe /W3 technom.asm /Fotechno.com
|
||||
; Assemble with JWasm: jwasm.exe -bin -Fo techno.com technom.asm
|
||||
; Assemble with Turbo Assembler: tasm.exe technom.asm techno.obj
|
||||
; tlink.exe /t techno.obj, techno.com
|
||||
|
||||
.model tiny
|
||||
.8086
|
||||
.code
|
||||
org 100h
|
||||
|
||||
start:
|
||||
push cs ; https://stackoverflow.com/a/53604793
|
||||
pop ds
|
||||
jmp main
|
||||
ifndef ??version ; Only pad if we're not Turbo Assembler (which will pad anyway)
|
||||
nop
|
||||
endif
|
||||
|
||||
exit:
|
||||
call disable_timer2
|
||||
mov ah, 4Ch ; Quit with exit code (AL)
|
||||
int 21h
|
||||
|
||||
; Params: SI=Bigchar Pointer
|
||||
; DI=Screen pos
|
||||
; AL=Character
|
||||
; AH=Cell Attrib
|
||||
; Side effects: SI += 7
|
||||
draw_bigchar:
|
||||
push di
|
||||
push bx
|
||||
push cx
|
||||
mov cx, 7
|
||||
next_line: ; for (j=0; j<7; ++j):
|
||||
push cx
|
||||
push di
|
||||
mov cx, 8
|
||||
mov bl, [si] ; BL = (*SI++)
|
||||
inc si
|
||||
cont_line: ; for (i=0; i<8; ++i):
|
||||
shl bl, 1 ; if (0x100 & BL <<= 1):
|
||||
jb plot_char ; plot_char()
|
||||
inc di ; DI += 2
|
||||
inc di
|
||||
loop cont_line
|
||||
end_line:
|
||||
pop di
|
||||
pop cx
|
||||
add di, 2 * 80 ; Next line
|
||||
loop next_line
|
||||
pop cx
|
||||
pop bx
|
||||
pop di
|
||||
ret
|
||||
plot_char: ; fn plot_char(AX, DI):
|
||||
stosw ; ES:[DI] = AX
|
||||
loop cont_line
|
||||
jmp end_line
|
||||
|
||||
; Arguments: DX = timer2 frequency
|
||||
beep:
|
||||
push ax
|
||||
mov al, 10110110b ; 0 - 16 bit mode
|
||||
; 1-3 - Mode 3 (Square wave generator)
|
||||
; 4-5 - Access mode: lobyte/hibyte
|
||||
; 6-7 - Channel 2
|
||||
out 43h, al ; Timer 8253-5 control bits
|
||||
mov al, dl
|
||||
out 42h, al ; Timer 8253-5 lo byte
|
||||
mov al, dh
|
||||
out 42h, al ; Timer 8253-5 hi byte
|
||||
in al, 61h ; Read 8255 port B state
|
||||
or al, 00000011b ; Enable Timer 2 Speaker
|
||||
out 61h, al ; Write 8255 B state
|
||||
pop ax
|
||||
ret
|
||||
|
||||
disable_timer2:
|
||||
push ax
|
||||
in al, 61h ; Read 8255 port state
|
||||
and al, 11111100b ; Disable Timer 2 Speaker
|
||||
out 61h, al ; Write 8255 state
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; Return: AX = 0040:006C - BIOS Counter
|
||||
get_counter:
|
||||
push ds
|
||||
mov ax, 40h ; Segment 0040 (BIOS)
|
||||
mov ds, ax
|
||||
mov ax, [ds:006Ch] ; AX = 0040:006C - BIOS Counter
|
||||
pop ds
|
||||
ret
|
||||
|
||||
; Wait for next BIOS counter tick
|
||||
wait_nexttick:
|
||||
push ax
|
||||
push bx
|
||||
call get_counter
|
||||
mov bx, ax
|
||||
busywait:
|
||||
call get_counter ; AX=BIOS counter
|
||||
cmp bx, ax
|
||||
jz busywait
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
main:
|
||||
mov ah, 0Fh
|
||||
int 10h ; Get current video mode (AL=mode, BH=curent page)
|
||||
mov bl, al
|
||||
mov ax, 0B800h ; Colour displays have their text buffer at B800:0000
|
||||
cmp bl, 7 ; Check if video mode is monochrome
|
||||
jnz not_mda
|
||||
mov ax, 0B000h ; Monochrome displays' buffer begins at B000:0000
|
||||
not_mda:
|
||||
mov es, ax ; Store video segment in Extra Segment
|
||||
mov ax, 07DCh ; Initial character Light Grey on Black, 0xDC
|
||||
mov dx, 0DFDCh ; Dancing cursor character pair, Lower half block, Upper half block
|
||||
mov bx, offset phrase
|
||||
mov cx, 80 * 25
|
||||
mov si, offset str_techno ; " TECHNO "
|
||||
xor di, di ; DI = 0
|
||||
main_loop:
|
||||
mov es:[di], ax ; Write cursor character
|
||||
test cl, 1 ; Skip over on odd cycles
|
||||
jnz odd_skip ; to run music code at half-speed
|
||||
push dx
|
||||
cmp byte ptr [bx], 0 ; FZ at the end of the musical phrase
|
||||
jnz goto_beep
|
||||
push ax
|
||||
push cx
|
||||
mov bx, offset freqtbl
|
||||
mov ax, [mangler]
|
||||
mov cx, 4
|
||||
loop_mangle_freqtbl: ; for (int i=0; i<4; ++i):
|
||||
xor [bx], ax ; Mangle the frequency LUT at the end of every measure
|
||||
inc bx
|
||||
inc bx
|
||||
loop loop_mangle_freqtbl
|
||||
pop cx
|
||||
pop ax
|
||||
mov bx, offset phrase
|
||||
goto_beep:
|
||||
push bx
|
||||
mov bl, [bx] ; Fetch current note index
|
||||
dec bl ; Phrase uses 1-based indicies because of the 0 terminator
|
||||
; So we need to convert it to 0-indexed
|
||||
mov bh, 0 ; BX &= 0xFF
|
||||
shl bl, 1 ;
|
||||
mov dx, [freqtbl + bx] ; Store frequency from note index into DX
|
||||
call beep ; Beep with loaded frequency
|
||||
pop bx
|
||||
pop dx
|
||||
inc bx
|
||||
odd_skip:
|
||||
call wait_nexttick ; Wait for next BIOS counter tick
|
||||
lodsb ; AL = DS:[SI] (get character)
|
||||
cmp al, 0
|
||||
jnz skip_nulterm
|
||||
mov si, offset str_techno ; Reset string on null terminator
|
||||
lodsb
|
||||
skip_nulterm:
|
||||
stosw ; Write string character
|
||||
xchg dl, dh ; Swap cursor half-blocks
|
||||
mov al, dl
|
||||
inc [mangler]
|
||||
push ax
|
||||
check_keyboard:
|
||||
mov ah, 1
|
||||
int 16h ; Check for keypresses (AH=scan code, AL=char, ZF=1 if buffer empty)
|
||||
jz no_keyboard_input
|
||||
mov ah, 0
|
||||
int 16h ; Read char from buffer (AH=scan code, AL=char)
|
||||
cmp al, 1Bh
|
||||
jnz skip_earlyexit
|
||||
inc [esc_counter] ; Exit if escape pressed twice
|
||||
cmp [esc_counter], 2
|
||||
jnz skip_earlyexit
|
||||
jmp exit
|
||||
skip_earlyexit:
|
||||
cmp si, offset str_notuch ; Avoid restarting notouch prompt if already active
|
||||
jnb notuch_skip
|
||||
mov si, offset str_notuch ; " >>Don't touch the keyboard<< "
|
||||
notuch_skip:
|
||||
jmp check_keyboard
|
||||
no_keyboard_input:
|
||||
pop ax
|
||||
loop main_loop ; Loop over every character on the screen
|
||||
call disable_timer2 ; Stop beeping
|
||||
mov di, 8 * 160 + 13 * 2 ; row=8, col=13
|
||||
mov ax, 07B0h ; FG=Light Grey on Black, Light shade block
|
||||
mov cx, 9
|
||||
loop_rows: ; for (j=0; j<9; ++j):
|
||||
push cx
|
||||
push di
|
||||
mov cx, 53 ; for (i=0; i<53; ++i):
|
||||
rep stosw ; (*ES:DI) = AX; DI += 2
|
||||
pop di
|
||||
pop cx
|
||||
add di, 80 * 2 ; row += 1
|
||||
loop loop_rows
|
||||
mov di, 9 * 160 + 15 * 2 ; row=9, col=15
|
||||
mov ah, 70h ; BG=Either Light Grey or White + Blink depending on video mode
|
||||
mov si, offset bigtext
|
||||
mov cx, 6
|
||||
mov bx, offset str_techno+2 ; "TECHNO"
|
||||
loop_bigchar: ; for (i=0; i<6; ++i):
|
||||
mov al, [bx] ; Load character into accum low
|
||||
inc bx ; Next character
|
||||
call draw_bigchar
|
||||
add di, 10h
|
||||
loop loop_bigchar
|
||||
mov cx, 20
|
||||
wait_loop:
|
||||
call wait_nexttick ; Wait for 20 ticks
|
||||
loop wait_loop
|
||||
mov ah, 0
|
||||
int 16h ; Wait for keypress
|
||||
xor di, di ; DI = 0
|
||||
mov cx, 80 * 25
|
||||
mov ax, 0720h ; FG=Light Grey on Black, space
|
||||
rep stosw ; Clear the whole screen
|
||||
jmp exit
|
||||
|
||||
str_techno db ' TECHNO ',0
|
||||
str_notuch db ' ',0AFh,'Don',27h,'t touch the keyboard',0AEh,' ',0
|
||||
|
||||
mangler dw 0404h
|
||||
freqtbl dw 5424, 2712, 2416, 2280
|
||||
phrase db 3 dup(3, 2, 1, 1, 2, 1, 1, 2, 1, 1), 3, 4, 3 dup(1, 4), 0
|
||||
|
||||
bigtext db 1111111b ; 'T'
|
||||
db 0001000b
|
||||
db 0001000b
|
||||
db 0001000b
|
||||
db 0001000b
|
||||
db 0001000b
|
||||
db 0001000b
|
||||
|
||||
db 1111111b ; 'E'
|
||||
db 1000000b
|
||||
db 1000000b
|
||||
db 1111100b
|
||||
db 1000000b
|
||||
db 1000000b
|
||||
db 1111111b
|
||||
|
||||
db 0111111b ; 'C'
|
||||
db 1000000b
|
||||
db 1000000b
|
||||
db 1000000b
|
||||
db 1000000b
|
||||
db 1000000b
|
||||
db 0111111b
|
||||
|
||||
db 1000001b ; 'H'
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
db 1111111b
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
|
||||
db 1000001b ; 'N'
|
||||
db 1100001b
|
||||
db 1010001b
|
||||
db 1001001b
|
||||
db 1000101b
|
||||
db 1000011b
|
||||
db 1000001b
|
||||
|
||||
db 0111110b ; 'O'
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
db 1000001b
|
||||
db 0111110b
|
||||
|
||||
esc_counter db 0
|
||||
|
||||
END start
|
||||
Reference in New Issue
Block a user