📄 mmenu.asm
字号:
; original version; uses buttons.
; suffers from needing a long keypress before submenu opens when menu is overlapped
; Also, should close other submenus (children!) when opening a new menu
;
; MENU APPLICATION
;
; Compile with FASM for Menuet
;
; Constants
OPTIONSFILE equ I_END + 256 ; Place for Menu Options File (8KB)
MENUTABLE equ OPTIONSFILE + 8192 ; Place for Menu Table, 8KB
OSWORKAREA equ MENUTABLE + 8192 ; Place for OS work area, 16KB
BPP equ 3 ; Number of bytes per pixel
BMPHEADER equ 18*3 ; Header part of bmp file
MENU_MAX_DEPTH equ 1024 ; Maximum depth of menu image
MENU_WIDTH equ 120 ; Maximum width of Panel image
; This is also a temporary work area for building the free-form
; window data
MENU_AREA equ OSWORKAREA + 0x4000
; memory location of 'constructed' image prior to display
MENU_IMAGE equ MENU_AREA + ( MENU_MAX_DEPTH * MENU_WIDTH )
; memory location of main bmp image read in from ram disk
BMP_MT equ MENU_IMAGE + ( BPP * MENU_MAX_DEPTH * MENU_WIDTH )
BMP_MT_WIDTH equ MENU_WIDTH ; The width of the original image
BMP_MT_DEPTH equ 20 ; The height of the bitmap image
BMP_MTF_DEPTH equ 5 ; The heigth of the submenu top image
BMP_MC equ 1024 + BMP_MT + BMPHEADER + (BPP * BMP_MT_DEPTH \
* (BMP_MT_WIDTH+3))
BMP_MC_WIDTH equ MENU_WIDTH ; The width of the original image
BMP_MC_DEPTH equ 34 ; The height of the bitmap image
BMP_MB equ 1024 + BMP_MC + BMPHEADER + (BPP * BMP_MC_DEPTH \
* (BMP_MC_WIDTH+3))
BMP_MB_WIDTH equ MENU_WIDTH ; The width of the original image
BMP_MB_DEPTH equ 54 ; The height of the bitmap image
ICON_FILE equ 1024 + BMP_MB + BMPHEADER + (BPP * BMP_MB_DEPTH \
* (BMP_MB_WIDTH+3))
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image ; could be much less
dd 0x100000 ; memory for app
dd 0x7fff0 ; esp
dd I_Param , 0x0 ; I_Param , I_Icon
;***************************************************************************
; Function
; START
;
; Description
; Entry point of the menu application
;
;***************************************************************************
START:
; Look at the input params - Menuname and position
call parseParams
; Read Menu options from file
call readMenuOptions
; Read the bitmaps
call readBitmaps
; Copy bitmaps into menu image
call buildMenuImage
; Create the free-form window definition, and apply it
call setWindowForm
call renderIcons
call draw_window
mov eax,60 ; IPC
mov ebx,1 ; define receive area
mov ecx,received_messages ; pointer to start
mov edx,1000 ; size of area
int 0x40
mov eax,40 ; WANTED EVENTS
mov ebx,01000111b ; IPC 7 + defaults
int 0x40
mov [received_messages+8],dword 0*256+0
mov [received_messages+12],dword 0
still:
mov eax, 23 ; wait here for event
mov ebx, 200
int 0x40
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
cmp eax, 7
je IPC
; Close app after 5 seconds of no activity - disabled
;; mov eax, -1
;; int 0x40
jmp still
IPC:
; Tell any child menus to close, then close myself
cmp [childPID], dword 0
je noSub
mov ecx, [childPID]
mov eax,9
mov ebx,OSWORKAREA
int 0x40
mov ecx, dword [OSWORKAREA + 30]
mov eax,60 ; IPC
mov ebx,2 ; send message
mov edx,received_messages ; Send any data
mov esi, 4
int 0x40
noSub:
mov eax, -1
int 0x40
jmp still
red: ; redraw
; get mouse x/y
mov eax, 37
mov ebx, 1
int 0x40
mov ebx, eax
shr ebx, 16 ; ebx = x
; Is the mouse in the window?
cmp ebx, MENU_WIDTH
jae nomenu
; Yes, so convert the y position to an index
; into the menu
mov ecx, eax
and ecx, 0xFFFF ; ecx = y
mov eax, ecx
; The 'buttons' start part way down the menu
; so add the appropriate offset
mov ecx, BMP_MT_DEPTH
cmp [menuType], byte 'M'
je @f
mov ecx, BMP_MTF_DEPTH
@@:
cmp eax, ecx
jb nomenu
sub eax, ecx
xor edx, edx
mov ecx, 34
div ecx
; Make sure we do not go 'below' the last button
cmp eax, [numOptions]
jae nomenu
cmp eax, [lastButton]
je nomenu
mov [lastButton], eax
; Mouse button pressed?
mov eax, 37
mov ebx, 2
int 0x40
cmp eax, 0
je nomenu
mov eax, [lastButton]
jmp dored
nomenu:
mov eax, -1
dored:
push eax
call draw_window
pop eax
cmp eax, -1
je still
shl eax, 4 ; Get button id
jmp dobutton
key: ; key
mov eax,2 ; just read it and ignore
int 0x40
jmp still
button: ; button
mov eax,17 ; get id
int 0x40
shr eax,8 ; Get button id
dobutton:
; Application or Menu?
mov ebx, [MENUTABLE + eax + 4]
cmp [ebx], byte 'A'
je launchApp
call runMenu
jmp still
launchApp:
call runApp
; Give a small delay - simultaneous app open / close is a problem
; in the kernel
mov eax, 5
mov ebx, 50
int 0x40
;; call closeMenus
;; ; Close me!
;; mov eax, -1
;; int 0x40
jmp still
;***************************************************************************
; Function
; closeMenus
;
; Description
; searches the process table for MMENU apps, and closes them
;
;***************************************************************************
closeMenus:
; Who am i :o)
mov eax, 9
mov ebx, OSWORKAREA ; Temporary work area
mov ecx, -1
int 0x40
mov ebx, [OSWORKAREA + 30] ; Get my PID
mov edi, appname
mov esi, OSWORKAREA + 10 ; Get app name, save
mov ecx, 12
cld
rep movsb
mov ecx, eax ; Get number of apps
cm001:
pusha
mov eax, 9
mov ebx, OSWORKAREA ; Temporary work area
int 0x40 ; get process info
popa
; Is this 'me'? If it is, dont kill me yet!
cmp [OSWORKAREA + 30], ebx
je cm002
; Is this a MMENU app to kill?
push ecx
mov edi, appname
mov esi, OSWORKAREA + 10
mov ecx, 12
repe cmpsb
cmp ecx, 0
pop ecx
jne cm002
; Close the app
mov ebx, 2
mov eax, 18
int 0x40
cm002:
loop cm001
ret
runApp:
; Copy the filename across
mov esi, [MENUTABLE + eax + 12]
mov edi, tmpfn
mov ecx, 256
cld
rep movsb
mov eax, 16
mov [tmpf], eax
xor eax, eax
mov [tmpf+4], eax
mov [tmpf+12], eax
mov eax, params
mov [tmpf+8], eax
mov [params], byte 0
; run the app
mov eax, 58
mov ebx, tmpf
int 0x40
ret
runMenu:
; If we are already running a menu, tell it to close
cmp [childPID], dword 0
je rm00b
push eax
mov ecx, [childPID]
mov eax,9
mov ebx,OSWORKAREA
int 0x40
mov ecx, dword [OSWORKAREA + 30]
mov eax,60 ; IPC
mov ebx,2 ; send message
mov edx,received_messages ; Send any data
mov esi, 4
int 0x40
pop eax
rm00b:
; Write in newX/Y the starting postion for the new menu
; open menu nearby the button we pressed
push eax ; Our button number
shr eax, 4
imul eax, 34
add eax, [startY]
add eax, 28
cmp [startX],dword MENU_WIDTH-10
jbe noyup
sub eax , 12
noyup:
mov [newY], eax
mov eax, [startX]
add eax, MENU_WIDTH - 3
mov [newX], eax
pop eax
mov esi, [MENUTABLE + eax + 12]
mov edi, params
mov ecx, 256
cld
rep movsb
; Now write across the startx and starty positions
mov edi, params ; Find the end of the first param
rm00a:
inc edi
cmp [edi], byte 0
jne rm00a
mov [edi], byte ' '
mov ecx, 4
add edi, ecx
mov eax, [newX]
mov ebx, 10
rm000:
xor edx, edx
div ebx
add dl, '0'
mov [edi], dl
dec edi
loop rm000
add edi, 5
mov [edi], byte ' '
mov ecx, 4
add edi, ecx
mov eax, [newY]
mov ebx, 10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -