mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
118 lines
3.4 KiB
NASM
118 lines
3.4 KiB
NASM
; blinkdi.asm -- resident blink hooked on the display interrupt, via the
|
|
; firmware's own RAM trampoline at bit 00000DB0h.
|
|
;
|
|
; HOW IT HOOKS
|
|
; The CPU vector table lives in ROM, but RLONG(0xFFFFFEA0) = 00000DB0h and
|
|
; that RAM word is a 6-byte `JA <handler>` stub. `install` rewrites the
|
|
; stub's 32-bit target to `entry` (the opcode C080h is unchanged). The
|
|
; original target 3F7146D0h is the OS display handler.
|
|
;
|
|
; WHY THE RETURN-PC TRAMPOLINE
|
|
; A one-shot VRAM draw is repainted before it reaches the screen. Drawing
|
|
; inside the handler *before* the OS handler runs is also wiped by the
|
|
; handler's own full-screen work. So:
|
|
; entry (runs first) saves the interrupt's return PC, replaces it with
|
|
; `ret_hook`, then tail-jumps to the stock OS handler;
|
|
; ret_hook (runs after the OS handler's `reti`) draws the box and jumps
|
|
; back to the saved PC. The draw is therefore after the repaint.
|
|
;
|
|
; The box is at framebuffer (256,400), 64x64, on the Terminal Manager's white
|
|
; body. State toggles every 0600h invocations (~48 frames at the measured
|
|
; ~32 display interrupts/frame): black <-> white.
|
|
;
|
|
; Linked at bit 01840000h by dwt/visual/build.sh.
|
|
|
|
.text
|
|
_start: ; install, called by rdebug `jump`
|
|
pushst
|
|
dint
|
|
setf 32, 0, 0
|
|
movi entry, a0, L
|
|
move a0, @00000DC0h, 0 ; stub target (32 bits, two words)
|
|
setf 16, 0, 0
|
|
movi 0C080h, a0, L ; JA opcode (unchanged value)
|
|
move a0, @00000DB0h, 0
|
|
sub a0, a0
|
|
move a0, @0186F000h, 0 ; invocation counter = 0
|
|
move a0, @0186F002h, 0 ; state = 0 (black)
|
|
popst
|
|
rets
|
|
|
|
; ---- entry hook: save return PC, install ret_hook, run stock handler ------
|
|
entry:
|
|
move a0, @0186F010h, 1 ; save interrupted a0
|
|
setf 32, 0, 1
|
|
move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC)
|
|
move a0, @0186F004h, 1 ; orig_pc
|
|
movi ret_hook, a0, L
|
|
move a0, *sp(020h), 1 ; return via ret_hook instead
|
|
move @0186F010h, a0, 1 ; restore a0
|
|
ja 3F7146D0h ; stock OS display handler
|
|
|
|
; ---- ret hook: after the OS handler, draw, then go back -----------------
|
|
ret_hook:
|
|
move a0, @0186F010h, 1
|
|
getst a0
|
|
move a0, @0186F014h, 1 ; save interrupted ST
|
|
dint
|
|
move a1, @0186F020h, 1
|
|
move a2, @0186F024h, 1
|
|
move a3, @0186F028h, 1
|
|
move a4, @0186F02Ch, 1
|
|
move a5, @0186F030h, 1
|
|
move b0, @0186F034h, 1
|
|
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move @0186F000h, a0, 0 ; counter
|
|
inc a0
|
|
move a0, @0186F000h, 0
|
|
cmpi 0600h, a0
|
|
jrne draw ; only flip state on wrap
|
|
sub a0, a0
|
|
move a0, @0186F000h, 0
|
|
move @0186F002h, a1, 0 ; current state
|
|
cmpi 0, a1
|
|
jrne was_white
|
|
movk 1, a1 ; 0 -> 1 (white)
|
|
jruc set_state
|
|
was_white:
|
|
sub a1, a1 ; 1 -> 0 (black)
|
|
set_state:
|
|
move a1, @0186F002h, 0
|
|
|
|
draw:
|
|
move @0186F002h, a1, 0
|
|
cmpi 0, a1
|
|
jrne pat_white
|
|
sub a2, a2 ; black
|
|
jruc pat_ready
|
|
pat_white:
|
|
movi 0FFFFh, a2, L ; white
|
|
pat_ready:
|
|
movi 04064100h, a3, L ; 04000000h + 400*1024 + 256
|
|
movi 64, a4, L ; 64 rows
|
|
movi 4, a5, L ; 4 words = 64 px
|
|
drow:
|
|
move a5, a1
|
|
dword:
|
|
move a2, *a3+, 0
|
|
dsjs a1, dword
|
|
addi 03C0h, a3 ; 1024 - 64 bits
|
|
dsjs a4, drow
|
|
|
|
move @0186F030h, a5, 1
|
|
move @0186F02Ch, a4, 1
|
|
move @0186F028h, a3, 1
|
|
move @0186F024h, a2, 1
|
|
move @0186F020h, a1, 1
|
|
; leave with orig_pc on the stack and every touched register restored
|
|
move @0186F004h, a0, 1 ; orig_pc
|
|
move a0, -*sp, 1 ; push return PC for `rets`
|
|
move @0186F010h, a0, 1 ; restore interrupted a0
|
|
move @0186F014h, b0, 1 ; interrupted ST
|
|
putst b0 ; restore IE/fields
|
|
move @0186F034h, b0, 1 ; restore interrupted b0
|
|
rets ; pop orig_pc and resume
|
|
.end
|