您的位置:首页 > 其它

简单MP3播放器

2008-04-13 20:25 309 查看
MP3Function.asm(MP3函数模块):

include winmm.inc
includelib winmm.lib
include masm32.inc
includelib masm32.lib

.const
nOpenState equ 1
nPlayState equ 2
nPauseState equ 3
nStopState equ 4
nCloseState equ 5
nLengthState equ 6
nPositionState equ 7
nModeState equ 8

.data
szMP3Tip db "MP3_Function",0
szPlayState db "playing",0
szPauseState db "paused",0
szStopState db "stopped",0
szMP3TimeFmt db "%d:%02d",0

;MCI格式命令
szCmdOpenFmt db "open ""%s""",0
szCmdPlayFmt db "play ""%s""",0
szCmdPlay2Fmt db "play ""%s"" from %d to %d",0 ;play 文件名 from 开始时间 to 结束时间
szCmdPauseFmt db "pause ""%s""",0
szCmdStopFmt db "stop ""%s""",0
szCmdCloseFmt db "Close ""%s""",0
szCmdLengthFmt db "status ""%s"" length",0 ;获取歌曲总长度
szCmdPositionFmt db "status ""%s"" Position",0 ;获取当前播放位置
szCmdModeFmt db "status ""%s"" mode",0 ;获取当前播放状态
.data?
szMP3FileName db MAX_PATH dup (?)
szCommand db 1024 dup (?)
szReturn db 1024 dup (?)
szError db 1024 dup (?)
.code
_CtrlMP3 proc _nState
local @nError

invoke RtlZeroMemory,addr szCommand,sizeof szCommand
invoke RtlZeroMemory,addr szReturn,sizeof szReturn
invoke RtlZeroMemory,addr szError,sizeof szError

.if _nState == nOpenState
invoke wsprintf,addr szCommand,addr szCmdOpenFmt,addr szMP3FileName
.elseif _nState == nPlayState
invoke wsprintf,addr szCommand,addr szCmdPlayFmt,addr szMP3FileName
.elseif _nState == nPauseState
invoke wsprintf,addr szCommand,addr szCmdPauseFmt,addr szMP3FileName
.elseif _nState == nStopState
invoke wsprintf,addr szCommand,addr szCmdStopFmt,addr szMP3FileName
.elseif _nState == nCloseState
invoke wsprintf,addr szCommand,addr szCmdCloseFmt,addr szMP3FileName
.elseif _nState == nLengthState
invoke wsprintf,addr szCommand,addr szCmdLengthFmt,addr szMP3FileName
.elseif _nState == nPositionState
invoke wsprintf,addr szCommand,addr szCmdPositionFmt,addr szMP3FileName
.elseif _nState == nModeState
invoke wsprintf,addr szCommand,addr szCmdModeFmt,addr szMP3FileName
.else
;错误的控制状态常量
.endif

invoke mciSendString,addr szCommand,addr szReturn,sizeof szReturn,NULL
mov @nError,eax
invoke mciGetErrorString,@nError,addr szError,sizeof szError
ret
_CtrlMP3 endp

_OpenMP3 proc _lpFileName
local @nError

movzx eax,BYTE ptr szMP3FileName
.if eax
invoke _CtrlMP3,nCloseState
.endif

invoke RtlMoveMemory,addr szMP3FileName,_lpFileName,MAX_PATH
invoke _CtrlMP3,nOpenState
ret
_OpenMP3 endp

_GetLengthMP3 proc
local @szRet[1024]:BYTE

invoke _CtrlMP3,nLengthState
invoke lstrcpy,addr @szRet,addr szReturn
mov @szRet[8],0
invoke atodw,addr @szRet
ret
_GetLengthMP3 endp

_GetPositionMP3 proc
local @szRet[1024]:BYTE

invoke _CtrlMP3,nPositionState
invoke lstrcpy,addr @szRet,addr szReturn
mov @szRet[8],0
invoke atodw,addr @szRet
ret
_GetPositionMP3 endp

_GetModeMP3 proc
local @szRet[1024]:BYTE
local @nRet

mov @nRet,3

invoke _CtrlMP3,nModeState
invoke lstrcpy,addr @szRet,addr szReturn
mov @szRet[8],0

invoke lstrcmp,addr @szRet,addr szPlayState
.if eax == 0
mov @nRet,1 ;playing
.endif

invoke lstrcmp,addr @szRet,addr szPauseState
.if eax == 0
mov @nRet,2 ;paused
.endif

invoke lstrcmp,addr @szRet,addr szStopState
.if eax == 0
mov @nRet,3 ;stopped
.endif

mov eax,@nRet
ret
_GetModeMP3 endp

_Play2MP3 proc _nFrom,_nTo
local @nError

invoke RtlZeroMemory,addr szCommand,sizeof szCommand
invoke RtlZeroMemory,addr szReturn,sizeof szReturn
invoke RtlZeroMemory,addr szError,sizeof szError

invoke wsprintf,addr szCommand,addr szCmdPlay2Fmt,addr szMP3FileName,_nFrom,_nTo
invoke mciSendString,addr szCommand,addr szReturn,sizeof szReturn,NULL
mov @nError,eax
invoke mciGetErrorString,@nError,addr szError,sizeof szError
ret
_Play2MP3 endp

_PlayMP3 proc
invoke _CtrlMP3,nPlayState
ret
_PlayMP3 endp

_PauseMP3 proc
invoke _CtrlMP3,nPauseState
ret
_PauseMP3 endp

_StopMP3 proc
invoke _CtrlMP3,nStopState
ret
_StopMP3 endp

_CloseMP3 proc
invoke _GetModeMP3
.if eax != 3 ;stopped
invoke _StopMP3
.endif
invoke _CtrlMP3,nCloseState

invoke RtlZeroMemory,addr szMP3FileName,sizeof szMP3FileName
ret
_CloseMP3 endp

_GetErrorMP3 proc
invoke MessageBox,NULL,addr szError,addr szMP3Tip,MB_OK
ret
_GetErrorMP3 endp

_GetReturnMP3 proc
invoke MessageBox,NULL,addr szReturn,addr szMP3Tip,MB_OK
ret
_GetReturnMP3 endp

_GetCommandMP3 proc
invoke MessageBox,NULL,addr szCommand,addr szMP3Tip,MB_OK
ret
_GetCommandMP3 endp

;向后跳跃(快退)
_BackMP3 proc uses edx
local @nFrom,@nTo,@temp

invoke _GetPositionMP3
mov @nFrom,eax

invoke _GetLengthMP3
mov @nTo,eax

mov @temp,10
mov eax,@nTo
xor edx,edx
div @temp ;EDX:EAX/SRC=EAX余EDX

.if @nFrom < eax
mov @nFrom,0
.else
sub @nFrom,eax
.endif

invoke _Play2MP3,@nFrom,@nTo
ret
_BackMP3 endp

;向前跳跃(快进)
_PrewMP3 proc uses edx
local @nFrom,@nTo,@temp

invoke _GetPositionMP3
mov @nFrom,eax

invoke _GetLengthMP3
mov @nTo,eax

mov @temp,10
mov eax,@nTo
xor edx,edx
div @temp ;EDX:EAX/SRC=EAX余EDX

add @nFrom,eax

mov eax,@nFrom
.if eax > @nTo
push @nTo
pop @nFrom
.endif

invoke _Play2MP3,@nFrom,@nTo
ret
_PrewMP3 endp

_Time2StrMP3 proc _dwTime,_lpBuffer,_dwMaxBuffer
local @szBuf[128]:BYTE
local @Min,@Sec

mov eax,_dwTime
xor edx,edx
mov ecx,60*1000
div ecx ;EDX:EAX/SRC=EAX余EDX
mov @Min,eax

mov eax,edx
xor edx,edx
mov ecx,1000
div ecx ;EDX:EAX/SRC=EAX余EDX
mov @Sec,eax

invoke wsprintf,addr @szBuf,addr szMP3TimeFmt,@Min,@Sec
invoke RtlMoveMemory,_lpBuffer,addr @szBuf,_dwMaxBuffer
ret
_Time2StrMP3 endp

_GetLength2StrMp3 proc _lpBuffer,_dwMaxBuffer
invoke _GetLengthMP3
invoke _Time2StrMP3,eax,_lpBuffer,_dwMaxBuffer
ret
_GetLength2StrMp3 endp

_GetPosition2StrMP3 proc _lpBuffer,_dwMaxBuffer
invoke _GetPositionMP3
invoke _Time2StrMP3,eax,_lpBuffer,_dwMaxBuffer
ret
_GetPosition2StrMP3 endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comctl32.inc
includelib comctl32.lib
include comdlg32.inc
includelib comdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.const
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1 ;主窗口图标ID
DLG_MAIN equ 1 ;主窗口ID
IDC_SLIDER equ 1 ;
IDC_APPEND equ 2 ;添加按钮ID
IDC_PLAY equ 3 ;播放按钮ID
IDC_PAUSE equ 4 ;暂停按钮ID
IDC_STOP equ 5 ;停止按钮ID
IDC_AFTER equ 6 ;上一首按钮ID
IDC_NEXT equ 7 ;下一首按钮ID
IDC_BACK equ 8 ;快退按钮ID
IDC_PREV equ 9 ;快进按钮ID
IDC_LIST_SNL equ 10 ;歌曲列表框ID
IDC_LIST_SPL equ 11 ;歌曲列表框(全路径文件名)ID
IDC_PLAN equ 12 ;进度Group框ID
IDC_PROGRESS equ 13 ;进度条ID
ID_TIMER equ 1 ;时钟ID,500ms
OF_MAX_PATH equ MAX_PATH*50 ;设置打开文件对话框最多可以允许选择50个MAX_PATH长文件名的文件
.data
szTmp_stOF_Filter db "Mp3 Files(*.mp3)",0,"*.mp3",0,"All Files(*.*)",0,"*.*",0,0
szININame db "Player.ini",0
szSNL_Section db "Sound Name List",0
szSPL_Section db "Sound Path List",0
szKeyFmt db "No%02d",0
szTimeFmt db "进度 %s[%s]",0
szTime1Fmt db "进度 0:00[0:00]",0
szFileFmt db "%s%s",0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
hInstance dd ?
hWinMain dd ?
hList_SNL dd ?
hList_SPL dd ?
szFullININame db MAX_PATH dup (?)
szTmp_stOF_lpstrFile db OF_MAX_PATH dup (?)
szTmp_stOF_lpstrFileTitle db MAX_PATH dup (?)
bPlaying dd ? ;播放状态标志
dwListCount dd ? ;歌曲列表总数
dwCurrentIndex dd ? ;当前播放歌曲列表索引号
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include _MyFunc.asm
include MP3Function.asm

_Play_Click proc
local @szBuffer[MAX_PATH]:BYTE

invoke _GetModeMP3
.if eax == 1 ;playing
invoke _StopMP3
.elseif eax == 2 ;paused
invoke _PlayMP3
mov bPlaying,TRUE
ret
.elseif eax == 3 ;stopped

.endif
invoke _CloseMP3
invoke SendMessage,hList_SNL,LB_GETCURSEL,0,0
mov dwCurrentIndex,eax
invoke SendMessage,hList_SPL,LB_GETTEXT,dwCurrentIndex,addr @szBuffer
invoke _OpenMP3,addr @szBuffer
;设置跟踪条范围
invoke _GetLengthMP3
invoke SendDlgItemMessage,hWinMain,IDC_PROGRESS,PBM_SETRANGE32,0,eax
;设置跟踪条起始位置
invoke _PlayMP3
mov bPlaying,TRUE
ret
_Play_Click endp

_Next_Click proc
invoke SendMessage,hList_SPL,LB_GETCOUNT,0,0
dec eax
.if dwCurrentIndex >= eax
mov dwCurrentIndex,0
.else
inc dwCurrentIndex
.endif
invoke SendMessage,hList_SNL,LB_SETCURSEL,dwCurrentIndex,0
invoke _Play_Click
ret
_Next_Click endp

_TimerProc proc uses ecx edx _hwnd,_uMsg,_idEvent,_dwTime
local @szBuf[128]:BYTE
local @szBuf1[128]:BYTE
local @szBuf2[128]:BYTE
local @nLength,@nPosition

.if bPlaying
invoke _GetLengthMP3
mov @nLength,eax
invoke _GetPositionMP3
mov @nPosition,eax

;设置状态条位置
invoke SendDlgItemMessage,hWinMain,IDC_PROGRESS,PBM_SETPOS,@nPosition,0

invoke _GetLength2StrMp3,addr @szBuf1,sizeof @szBuf1
invoke _GetPosition2StrMP3,addr @szBuf2,sizeof @szBuf2
invoke wsprintf,addr @szBuf,addr szTimeFmt,addr @szBuf1,addr @szBuf2
invoke SendDlgItemMessage,hWinMain,IDC_PLAN,WM_SETTEXT,0,addr @szBuf

mov eax,@nPosition
.if eax == @nLength
invoke _CloseMP3
invoke _Next_Click
.endif
.endif
ret
_TimerProc endp

_LoadList proc uses esi ecx
local @szBuf1[OF_MAX_PATH]:BYTE
local @szBuf2[MAX_PATH]:BYTE
local @Temp

invoke SendMessage,hList_SNL,LB_RESETCONTENT,0,0 ;清空播放列表框
invoke SendMessage,hList_SPL,LB_RESETCONTENT,0,0 ;清空播放列表框
invoke RtlZeroMemory,addr @szBuf1,sizeof @szBuf1
invoke GetPrivateProfileString,addr szSNL_Section,NULL,NULL,addr @szBuf1,sizeof @szBuf1,addr szFullININame
lea esi,@szBuf1
.while BYTE ptr [esi]
invoke RtlZeroMemory,addr @szBuf2,MAX_PATH
invoke GetPrivateProfileString,addr szSNL_Section,esi,NULL,addr @szBuf2,MAX_PATH,addr szFullININame
invoke SendMessage,hList_SNL,LB_ADDSTRING,0,addr @szBuf2
invoke lstrlen,esi
add esi,eax
inc esi
.endw

invoke RtlZeroMemory,addr @szBuf1,sizeof @szBuf1
invoke GetPrivateProfileString,addr szSPL_Section,NULL,NULL,addr @szBuf1,sizeof @szBuf1,addr szFullININame
mov @Temp,0
lea esi,@szBuf1
.while BYTE ptr [esi]
invoke RtlZeroMemory,addr @szBuf2,MAX_PATH
invoke GetPrivateProfileString,addr szSPL_Section,esi,NULL,addr @szBuf2,MAX_PATH,addr szFullININame
invoke SendMessage,hList_SPL,LB_ADDSTRING,NULL,addr @szBuf2
inc @Temp
invoke lstrlen,esi
add esi,eax
inc esi
.endw

push @Temp
pop dwListCount
mov dwCurrentIndex,0
invoke SendMessage,hList_SNL,LB_SETCURSEL,dwCurrentIndex,0
ret
_LoadList endp

_SaveList proc _lpstrFile,_lpstrFileTitle
local @szBuf[128]:BYTE

invoke SendMessage,hList_SPL,LB_FINDSTRING,0,_lpstrFile
.if eax != LB_ERR
mov dwCurrentIndex,eax
ret
.endif
invoke SendMessage,hList_SNL,LB_ADDSTRING,NULL,_lpstrFileTitle
invoke SendMessage,hList_SPL,LB_ADDSTRING,NULL,_lpstrFile

invoke SendMessage,hList_SPL,LB_GETCOUNT,0,0
invoke wsprintf,addr @szBuf,addr szKeyFmt,eax
invoke WritePrivateProfileString,addr szSNL_Section,addr @szBuf,_lpstrFileTitle,addr szFullININame
invoke WritePrivateProfileString,addr szSPL_Section,addr @szBuf,_lpstrFile,addr szFullININame
ret
_SaveList endp

_OpenFileDialog proc uses ecx edx
local @stOF:OPENFILENAME
local @szBuf[MAX_PATH]:BYTE
local @szTmp_Path[MAX_PATH]:BYTE
local @szTmp_File[MAX_PATH]:BYTE
local @dwTmp_MaxFile,@dwTmp_Length

invoke RtlZeroMemory,addr @stOF,sizeof @stOF
mov @stOF.lStructSize,sizeof @stOF
push hWinMain
pop @stOF.hwndOwner
mov @stOF.lpstrFilter,offset szTmp_stOF_Filter
invoke RtlZeroMemory,addr szTmp_stOF_lpstrFile,OF_MAX_PATH ;OF_MAX_PATH=MAX_PATH*50
mov @stOF.lpstrFile,offset szTmp_stOF_lpstrFile
mov @stOF.nMaxFile,OF_MAX_PATH
invoke RtlZeroMemory,addr szTmp_stOF_lpstrFileTitle,MAX_PATH
mov @stOF.lpstrFileTitle,offset szTmp_stOF_lpstrFileTitle
mov @stOF.nMaxFileTitle,MAX_PATH
mov @stOF.Flags,OFN_EXPLORER or OFN_HIDEREADONLY or OFN_ALLOWMULTISELECT or OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES
invoke GetOpenFileName,addr @stOF
.if eax
lea ebx,szTmp_stOF_lpstrFile ;多选时用。
invoke lstrlen,ebx
mov @dwTmp_Length,eax ;多选时用。
mov @dwTmp_MaxFile,eax ;多选时用。统计szTmp_stOF_lpstrFile全路径文件名长度
inc @dwTmp_MaxFile
movzx edx,@stOF.nFileOffset
.if eax > edx ;用户只选了一个文件
invoke MessageBox,NULL,addr szTmp_stOF_lpstrFile,addr szTmp_stOF_lpstrFile,0
invoke MessageBox,NULL,addr szTmp_stOF_lpstrFileTitle,addr szTmp_stOF_lpstrFileTitle,0
invoke _SaveList,addr szTmp_stOF_lpstrFile,addr szTmp_stOF_lpstrFileTitle
.else
;多选格式:"F:mp3,0,1.mp3,0,2.mp3,0,0"
invoke RtlZeroMemory,addr @szTmp_Path,MAX_PATH
invoke RtlMoveMemory,addr @szTmp_Path,ebx,@dwTmp_Length
;invoke MessageBox,NULL,addr @szTmp_Path,addr @szTmp_Path,0
add ebx,@dwTmp_MaxFile
.while BYTE ptr [ebx] != 0
invoke lstrlen,ebx
mov @dwTmp_Length,eax
add @dwTmp_MaxFile,eax
inc @dwTmp_MaxFile
.break .if @dwTmp_MaxFile >= OF_MAX_PATH
invoke RtlZeroMemory,addr @szTmp_File,MAX_PATH
invoke RtlMoveMemory,addr @szTmp_File,ebx,@dwTmp_Length
;invoke MessageBox,NULL,addr @szTmp_File,addr @szTmp_File,0
invoke RtlZeroMemory,addr @szBuf,MAX_PATH
invoke wsprintf,addr @szBuf,addr szFileFmt,addr @szTmp_Path,addr @szTmp_File
invoke _SaveList,addr @szBuf,addr @szTmp_File
add ebx,@dwTmp_Length
inc ebx
.endw
.endif
.endif
ret
_OpenFileDialog endp

_ProcDlgMain proc uses ecx ebx edi esi _hWnd,_wMsg,_wParam,_lParam
mov eax,_wMsg
.if eax == WM_CLOSE
invoke _StopMP3
invoke _CloseMP3
invoke KillTimer,_hWnd,ID_TIMER
invoke EndDialog,_hWnd,NULL
.elseif eax == WM_INITDIALOG
push _hWnd
pop hWinMain

invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWinMain,WM_SETICON,ICON_SMALL,eax

invoke GetDlgItem,hWinMain,IDC_LIST_SNL
mov hList_SNL,eax

invoke GetDlgItem,hWinMain,IDC_LIST_SPL
mov hList_SPL,eax

invoke ShowWindow,hList_SPL,SW_HIDE
invoke GetCurrentDirectory,MAX_PATH,addr szFullININame
mov esi,offset szFullININame
invoke lstrlen,esi
mov ecx,offset szININame
.if BYTE ptr [esi+eax-1] == ''
inc ecx
.endif
invoke lstrcat,esi,ecx

invoke _LoadList
invoke SetTimer,hWinMain,ID_TIMER,500,offset _TimerProc
.elseif eax == WM_COMMAND
mov eax,_wParam
.if ax == IDC_APPEND
invoke _OpenFileDialog
.elseif ax == IDC_PLAY
invoke _Play_Click
.elseif ax == IDC_PAUSE
invoke _PauseMP3
mov bPlaying,FALSE
;invoke SendDlgItemMessage,_hWnd,IDC_PLAN,WM_SETTEXT,0,addr szTime1Fmt
;invoke SendDlgItemMessage,_hWnd,IDC_PROGRESS,PBM_SETPOS,0,0
.elseif ax == IDC_STOP
invoke _StopMP3
invoke _CloseMP3
mov bPlaying,FALSE
invoke SendDlgItemMessage,_hWnd,IDC_PLAN,WM_SETTEXT,0,addr szTime1Fmt
invoke SendDlgItemMessage,_hWnd,IDC_PROGRESS,PBM_SETPOS,0,0
.elseif ax == IDC_AFTER ;上一首按钮
.if dwCurrentIndex <= 0
invoke SendMessage,hList_SPL,LB_GETCOUNT,0,0
dec eax
mov dwCurrentIndex,eax
.else
dec dwCurrentIndex
.endif
invoke SendMessage,hList_SNL,LB_SETCURSEL,dwCurrentIndex,0
invoke _Play_Click
.elseif ax == IDC_NEXT ;下一首按钮
invoke _Next_Click
.elseif ax == IDC_BACK ;快退按钮
invoke _BackMP3
.elseif ax == IDC_PREV ;快进按钮
invoke _PrewMP3
.elseif ax == IDC_LIST_SNL ;歌曲列表框控件
shr eax,16
.if ax == LBN_DBLCLK
invoke _Play_Click
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke InitCommonControls
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start

MP3Player.asm(主程序文件):
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: