哈哈,新板块,这么多兄弟来这里冒过泡,看来我是来迟了。
写点东西大家分享分享,首先声明,我编程很菜,写出来的东西有点像我们专业-土木,又土又木!
这不是什么高明的文章,可我找这方面的资料也很久了,却也是不多见。我曾在DFCG见过springkang翻译的一篇<<如何在自己的代码中播放XM音乐>>,不过那是C++的,而且要用很多附加工具,比如要用Table Extractor抓取C++格式的XM内容,这样实现起来有点不方便。我在这里介绍一种相对比较方便的实现方法,可以在资源中直接使用xm文件,编译语言就不用说了,肯定是汇编。
在介绍方法之前,我想介绍一个XM播放支持库,叫mfmplayer.lib,是个叫Lise_Grim的老外写的,大家可以用Google找到,如果去主页,记得要用国外的代理,不然你上不去,更别说下载了。不过这个mfmplayer.lib存在一些问题,我的汇编环境变量设置在了系统变量中,如果哪位也是和我一样的设置,那就请先做一件事,UltraEdit打开mfmplayer.lib,查找\masm32\lib\,把后面的*.lib移到\masm32\lib\所在的地址,后面部分用00填充,我修改过,一共有三个。如果哪位哥们找不到这个mfmplayer.lib,或者懒得去修改,可以下载附件里的(我修改好了)。修改完了以后,把mfmplayer.lib复制到masm32\lib下,当然还有一个mfmplayer.inc复制到masm32\include下面。完成后,就可开始写个播放XM的注册机了(当然,这个mfmplayer.lib不是仅仅可以用在注册机上)。
使用mfmplayer.lib播放XM音乐,先熟悉它最主要的函数mfmPlay。我们可以调用这个函数来播放,也可以用它来停止播放。原型如下:
mfmPlay PROTO :DWORD
只有一个参数,当dword为xm资源文件在内存的偏移值是,开始加载模块并播放,当dword为0时,停止播放并释放模块。
mfmplayer.lib里还有另外两个函数,mfmGetPos和mfmPause,用来获取播放位置和暂停,我就不说了,大家也可以参考mfmplayer.inc里说明,我孤陋寡闻,不知道那是哪国文字,有点像英语,内容不多,凑合能看懂。
废话一大堆,还是放段代码上来大家看看,里面还有滚动字幕的实现方法,我注释了很多地方,希望大家看了代码,立刻就能明白。
小弟我大胆,在鲁班门前耍大斧,让各位见笑了。
;-----------------------------------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>> 在注册机里使用xm产生背景音乐的例子 >>
;>> 编写: qfejj >>
;>> Email :qfejj@163.com >>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.586
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include kernel32.inc
include gdi32.inc
include user32.inc
include mfmplayer.inc ;xm播放支持
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
includelib user32.lib
includelib mfmplayer.lib ;xm播放支持库
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDD_MAINDLG equ 1000
IDC_EDT1 equ 1003
IDC_EDT2 equ 1004
IDM_MUSIC equ 50 ;声音资源
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Windowproc proto :HWND,:UINT,:WPARAM,:LPARAM
GetRegistKey proto
Color macro Red,Green,Blue ;宏,方便后面颜色设置
xor eax,eax
mov ah,Blue
shl eax,8
mov ah,Green
mov al,Red
endm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
String db 'Keygen Template with XM Music ',0dh,0ah
db ' Designed by qfejj',0dh,0ah
db 'Contact Email: qfejj@163.com ',0dh,0ah
db ' ========================== ',0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance HINSTANCE ?
hWnd HINSTANCE ?
NameBuffer db 32 dup(?)
;音乐
nMusicSize DWORD ?
pMusic LPVOID ?
;滚动字幕
hDc DWORD ?
hMemoryDc1 DWORD ?
hMemoryDc2 DWORD ?
hBrush DWORD ?
TextOutX DWORD ?
TextOutY DWORD ?
TextOutCY DWORD ?
LogFont LOGFONT <?>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke GetModuleHandle,0
mov hInstance,eax
invoke DialogBoxParam,hInstance,IDD_MAINDLG,0,offset Windowproc,0
invoke ExitProcess,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Windowproc PROC hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hBitMapMDc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT
LOCAL TextSizeCX:dword
LOCAL TextSizeCY:dword
mov eax,uMsg
.if eax == WM_PAINT
invoke BeginPaint,hWin,addr ps
mov hDc,eax
Color 0,0,0
invoke BitBlt,hDc,0h,0h,100h,40h,hMemoryDc1,0,0,eax ;将全黑位图从设备场景hMemoryDc1复制到hDc
invoke EndPaint,hWin,addr ps
.elseif eax == WM_INITDIALOG
;---------------------------------------------------------- ;==加载音乐,播放==
push esi
invoke FindResource,hInstance,IDM_MUSIC,RT_RCDATA ;在模块中查找指定的资源,这里是xm文件
push eax
invoke SizeofResource,hInstance,eax
mov nMusicSize, eax
pop eax
invoke LoadResource,hInstance,eax
invoke LockResource,eax
mov esi,eax
mov eax,nMusicSize
add eax,sizeof nMusicSize
invoke GlobalAlloc,GPTR,eax
mov pMusic,eax
mov ecx,nMusicSize
mov dword ptr[eax],ecx
add eax,sizeof nMusicSize
mov edi,eax
rep movsb
pop esi
invoke mfmPlay,pMusic ;mfmPlay.lib中播放XM的函数
;----------------------------------------------------------- ;==实现滚动字幕==
invoke SetTimer,hWin,200h,45h,NULL
invoke GetDC,hWin
mov hDc,eax
invoke CreateCompatibleDC,hDc ;创建作为大背景的内存设备环境
mov hMemoryDc1,eax
invoke CreateCompatibleBitmap,hDc,100h,40h ;创建位图,以供内存设备环境调用作大背景
mov hBitMapMDc,eax
invoke SelectObject,hMemoryDc1,hBitMapMDc ;选入刚创建的位图到内存设备环境
Color 0,0,0 ;设置画刷的颜色
invoke CreateSolidBrush,eax
mov hBrush,eax
mov rect.top,0h ;设置矩形大小
mov rect.left,0h
mov rect.right,100h
mov rect.bottom,100h
invoke FillRect,hMemoryDc1,addr rect,hBrush ;用画刷以矩形大小填充内大背景
invoke DeleteObject,hBrush
invoke CreateCompatibleDC,hDc ;创建一个带文字的内存设备
mov hMemoryDc2,eax
Color 255,0,0 ;设置字体颜色
invoke SetTextColor,hMemoryDc2,eax
invoke SetBkMode,hMemoryDc2,TRANSPARENT ;指定空隙的填充方式-TRANSPARENT-透明处理
invoke CreateFontIndirect,addr LogFont ;创建可以被选入的文字
invoke SelectObject,hMemoryDc2,eax
invoke CreateCompatibleBitmap,hDc,100h,80h ;可显示的文字范围
invoke SelectObject,hMemoryDc2,eax
Color 0,0,0 ;@1--设置画刷的颜色
invoke CreateSolidBrush,eax
mov hBrush,eax
mov rect.top,0h ;设置矩形大小
mov rect.left,0h
mov rect.right,100h
mov rect.bottom,100h
invoke FillRect,hMemoryDc2,addr rect,hBrush ;填充文字背景,单色时,从@1到这里的代码可以不用
invoke DeleteObject,hBrush
mov TextOutX,22h
mov TextOutY,30h
lea esi,String
mov al,byte ptr [esi]
.while al
.if al == 0dh
add TextOutY,10h ;设置行间距
mov TextOutX,22h ;换行
add esi,2h
.else
invoke GetTextExtentPoint32,hMemoryDc2,esi,1,addr TextSizeCX
invoke TextOut,hMemoryDc2,TextOutX,TextOutY,esi,1h
mov eax,TextSizeCX
add TextOutX,eax
inc esi
.endif
mov al,byte ptr [esi]
.endw
invoke ReleaseDC,hWin,hDc
.elseif eax == WM_TIMER
invoke GetDC,hWin
mov hDc,eax
invoke BitBlt,hMemoryDc1,0h,8h,100h,40h,hMemoryDc2,0,TextOutCY,0cc0020h
inc TextOutCY
.if TextOutCY == 70h
mov TextOutCY,0
.endif
invoke BitBlt,hDc,0h,0h,100h,38h,hMemoryDc1,0,0,0cc0020h
invoke ReleaseDC,hWin,hDc
.elseif eax == WM_CLOSE
invoke EndDialog,hWin,0
invoke mfmPlay,0 ;停止音乐的播放
invoke GlobalFree, pMusic ;释放背景音乐使用的内存
.elseif eax == WM_COMMAND
mov eax,wParam
.if eax ==IDOK
push hWin
pop hWnd
invoke GetRegistKey ;自定义算码函数
.endif
.else
mov eax,0
ret
.endif
mov eax,1
ret
Windowproc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetRegistKey proc
invoke GetDlgItemText,hWnd,IDC_EDT1,offset NameBuffer,sizeof NameBuffer
invoke SetDlgItemText,hWnd,IDC_EDT2,addr NameBuffer
ret
GetRegistKey endp
end start
;---------------------------------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>> keygen.rc >>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define MANIFEST 24
#define IDD_MAINDLG 1000
#define IDOK 1
#define IDC_EDT1 1003
#define IDC_EDT2 1004
#define IDC_STC1 1005
#define IDC_STC2 1006
#define IDC_GRP1 1007
#define IDM_MUSIC 50
IDD_MAINDLG DIALOGEX 4,4,145,112
CAPTION "Kegen for program"
FONT 10,"宋体"
STYLE 0x10CA0880
EXSTYLE 0x00000001
BEGIN
CONTROL "计算",IDOK,"Button",0x50010000,52,93,41,15,0x00000000
CONTROL "",IDC_EDT1,"Edit",0x50010000,46,49,87,12,0x00000200
CONTROL "",IDC_EDT2,"Edit",0x50010800,46,67,87,12,0x00000200
CONTROL "用户名:",IDC_STC1,"Static",0x50000201,13,49,30,12,0x00000000
CONTROL "注册码:",IDC_STC2,"Static",0x50000201,13,69,30,12,0x00000000
CONTROL "",IDC_GRP1,"Button",0x50000007,7,40,132,47,0x00000000
END
1008 ICON DISCARDABLE "ccg.ico"
IDM_MUSIC RCDATA DISCARDABLE "keygen.xm" ;自己找一个xm文件换上就可以了
;---------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
附件:mfmplayer.rar