📄 dma.asm
字号:
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%include "macros.mac"
EXTSYM memtabler8,regptw,snesmap2,snesmmap,debstop3
;EXTSYM soundcycleft,pexecs2
EXTSYM memtablew8,regptr
EXTSYM dmadata
EXTSYM hdmatype
EXTSYM nexthdma
EXTSYM curhdma,curypos,disablehdma,hdmadata,hdmadelay,hdmaearlstart
EXTSYM resolutn
EXTSYM memtabler16
NEWSYM DmaAsmStart
;*******************************************************
; Transfer DMA Inits & Transfers DMA
;*******************************************************
; DMA transfer register
NEWSYM AddrNoIncr, db 0
%macro ExecSPCCycles 0
xor ebx,ebx
mov bx,[esi+5]
inc bx
inc ebx
shr ebx,2
mov [soundcycleft],ebx
or ebx,ebx
jz .nocycles
xor ebx,ebx
xor ecx,ecx
call pexecs2
.nocycles
%endmacro
NEWSYM transdma
push eax
cmp word[esi+5],480h
jne .no
; mov byte[debstop3],1
.no
; ExecSPCCycles
mov al,[esi]
test al,80h
jnz near transdmappu2cpu
; set address increment value
mov dword[.addrincr],0
test al,00001000b
jnz .skipaddrincr
test al,00010000b
jnz .autodec
mov dword[.addrincr],1
jmp .skipaddrincr
.autodec
mov dword[.addrincr],0FFFFFFFFh
.skipaddrincr
mov byte[AddrNoIncr],0
cmp dword[.addrincr],0
jne .notzero
mov byte[AddrNoIncr],1
.notzero
; get address order to be written
xor ebx,ebx
and al,00000111b
cmp al,5
jne .notmode5dma
mov al,1
.notmode5dma
mov bl,al
shl bl,3
add ebx,.addrwrite
mov edi,ebx
; get pointer #1
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi]
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [.regptra],eax
; get pointer #2
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+2]
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [.regptrb],eax
; get pointer #3
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+4]
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [.regptrc],eax
; get pointer #4
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+6]
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [.regptrd],eax
mov dx,[esi+5] ; Number of bytes to transfer
xor ebx,ebx
mov bl,[esi+4] ; Bank #
mov ecx,[esi+2] ; address offset #
and ecx,0FFFFh
mov [.curbank],bl
mov word[esi+5],0
mov ebx,[.curbank]
mov eax,snesmap2
test ecx,8000h
jz .nomap1
mov eax,snesmmap
.nomap1
and edx,0FFFFh
mov ebx,[eax+ebx*4]
;snesmmap times 256 dd 0 ; addresses 8000-FFFF
;snesmap2 times 256 dd 0 ; addresses 0000-7FFF
push esi
mov esi,ebx
xor ebx,ebx
mov bl,[.curbank]
; do loop
cmp edx,0
jne .no0
mov edx,65536
.no0
mov ebx,[memtabler8+ebx*4]
mov [.readaddr],ebx
xor ebx,ebx
mov bl,[.curbank]
mov [.cebx],ebx
.againloop
cmp edx,4
jbe .deccheckloop
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptra]
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptrb]
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptrc]
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptrd]
sub edx,4
jmp .againloop
.deccheckloop
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptra]
dec edx
jz .findma
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptrb]
dec edx
jz .findma
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptrc]
dec edx
jz .findma
mov ebx,[.cebx]
call dword near [.readaddr]
add cx,[.addrincr]
call dword near [.regptrd]
.findma
pop esi
mov [esi+2],cx
pop eax
mov byte[AddrNoIncr],0
ret
ALIGN32
.curbank dd 0
.addrincr dd 0
.addrwrite dw 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,0,1,1, 0,1,2,3, 0,1,2,3, 0,1,2,3
dw 0,1,2,3
; pointer address of registers
.regptra dd 0
.regptrb dd 0
.regptrc dd 0
.regptrd dd 0
.readaddr dd 0
.cebx dd 0
NEWSYM transdmappu2cpu
; set address increment value
mov dword[.addrincr],0
test al,00001000b
jnz .skipaddrincr
test al,00010000b
jnz .autodec
mov dword[.addrincr],1
jmp .skipaddrincr
.autodec
mov dword[.addrincr],0FFFFFFFFh
.skipaddrincr
; get address order to be written
xor ebx,ebx
and al,00000111b
mov bl,al
shl bl,3
add ebx,.addrwrite
mov edi,ebx
; get pointer #1
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi]
shl ebx,2
add ebx,[regptr]
mov eax,[ebx]
mov [.regptra],eax
; get pointer #2
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+2]
shl ebx,2
add ebx,[regptr]
mov eax,[ebx]
mov [.regptrb],eax
; get pointer #3
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+4]
shl ebx,2
add ebx,[regptr]
mov eax,[ebx]
mov [.regptrc],eax
; get pointer #4
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+6]
shl ebx,2
add ebx,[regptr]
mov eax,[ebx]
mov [.regptrd],eax
mov dx,[esi+5] ; Number of bytes to transfer
xor ebx,ebx
mov bl,[esi+4] ; Bank #
mov ecx,[esi+2] ; address offset #
and ecx,0FFFFh
mov [.curbank],bl
mov word[esi+5],0
mov ebx,[.curbank]
mov eax,snesmap2
test ecx,8000h
jz .nomap1
mov eax,snesmmap
.nomap1
and edx,0FFFFh
mov ebx,[eax+ebx*4]
;snesmmap times 256 dd 0 ; addresses 8000-FFFF
;snesmap2 times 256 dd 0 ; addresses 0000-7FFF
push esi
mov esi,ebx
xor ebx,ebx
mov bl,[.curbank]
; do loop
cmp edx,0
jne .no0
mov edx,65536
.no0
mov ebx,[memtablew8+ebx*4]
mov [.writeaddr],ebx
xor ebx,ebx
mov bl,[.curbank]
mov [.cebx],ebx
.againloop
cmp edx,4
jbe .deccheckloop
call dword near [.regptra]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
call dword near [.regptrb]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
call dword near [.regptrc]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
call dword near [.regptrd]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
sub edx,4
jmp .againloop
.deccheckloop
call dword near [.regptra]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
dec edx
jz .findma
call dword near [.regptrb]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
dec edx
jz .findma
call dword near [.regptrc]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
dec edx
jz .findma
call dword near [.regptrd]
mov ebx,[.cebx]
call dword near [.writeaddr]
add cx,[.addrincr]
.findma
pop esi
mov [esi+2],cx
pop eax
ret
ALIGN32
.curbank dd 0
.addrincr dd 0
.addrwrite dw 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,0,1,1, 0,1,2,3, 0,1,2,3, 0,1,2,3
dw 0,1,2,3
; pointer address of registers
.regptra dd 0
.regptrb dd 0
.regptrc dd 0
.regptrd dd 0
.writeaddr dd 0
.cebx dd 0
%macro TestDMA 0
%endmacro
; DMA enable register
; use dmadata for input on dma
NEWSYM reg420Bw
push eax
push esi
push edi
push ecx
push edx
mov esi,dmadata
test al,01h
jz .notransa
TestDMA
call transdma
.notransa
add esi,16
test al,02h
jz .notransb
TestDMA
call transdma
.notransb
add esi,16
test al,04h
jz .notransc
TestDMA
call transdma
.notransc
add esi,16
test al,08h
jz .notransd
TestDMA
call transdma
.notransd
add esi,16
test al,10h
jz .notranse
TestDMA
call transdma
.notranse
add esi,16
test al,20h
jz .notransf
TestDMA
call transdma
.notransf
add esi,16
test al,40h
jz .notransg
TestDMA
call transdma
.notransg
add esi,16
test al,80h
jz .notransh
TestDMA
call transdma
.notransh
pop edx
pop ecx
pop edi
pop esi
pop eax
ret
;*******************************************************
; HDMA Settings
;*******************************************************
NEWSYM setuphdma
push eax
; transfer old address to new address
mov ax,[esi+2]
mov [esi+8],ax
mov [edx+17],ax
; get address order to be written
xor ebx,ebx
xor eax,eax
xor ecx,ecx
mov al,[esi]
and al,00000111b
mov ah,[.addrnumt+eax]
mov [edx+16],ah
mov bl,al
shl bl,3
add ebx,.addrwrite
mov edi,ebx
; get pointer #1
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi]
cmp bx,2118h
je .notnormalhdma1
cmp bx,2119h
je .notnormalhdma1
jmp .normalhdma1
.notnormalhdma1
mov bx,2200h ; bad hack _Demo_
.normalhdma1
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx],eax
; get pointer #2
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+2]
cmp bx,2118h
je .notnormalhdma2
cmp bx,2119h
je .notnormalhdma2
jmp .normalhdma2
.notnormalhdma2
mov bx,2200h ; bad hack _Demo_
.normalhdma2
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+4],eax
; get pointer #3
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+4]
cmp bx,2118h
je .notnormalhdma3
cmp bx,2119h
je .notnormalhdma3
jmp .normalhdma3
.notnormalhdma3
mov bx,2200h ; bad hack _Demo_
.normalhdma3
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+8],eax
; get pointer #4
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+6]
cmp bx,2118h
je .notnormalhdma4
cmp bx,2119h
je .notnormalhdma4
jmp .normalhdma4
.notnormalhdma4
mov bx,2200h ; bad hack _Demo_
.normalhdma4
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+12],eax
xor ebx,ebx
mov byte[esi+10],0
pop eax
or [hdmatype],ah
ret
.addrwrite dw 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,0,1,1, 0,1,2,3, 0,1,2,3, 0,1,2,3
dw 0,1,2,3
.addrnumt db 1,2,2,4,4,4,4,4
NEWSYM setuphdmars
push eax
; get address order to be written
xor ebx,ebx
xor eax,eax
xor ecx,ecx
mov al,[esi]
and al,00000111b
mov ah,[.addrnumt+eax]
mov [edx+16],ah
mov bl,al
shl bl,3
add ebx,.addrwrite
mov edi,ebx
; get pointer #1
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi]
cmp bx,2118h
je .notnormalhdma1
cmp bx,2119h
je .notnormalhdma1
jmp .normalhdma1
.notnormalhdma1
mov bx,2200h ; bad hack _Demo_
.normalhdma1
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx],eax
; get pointer #2
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+2]
cmp bx,2118h
je .notnormalhdma2
cmp bx,2119h
je .notnormalhdma2
jmp .normalhdma2
.notnormalhdma2
mov bx,2200h ; bad hack _Demo_
.normalhdma2
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+4],eax
; get pointer #3
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+4]
cmp bx,2118h
je .notnormalhdma3
cmp bx,2119h
je .notnormalhdma3
jmp .normalhdma3
.notnormalhdma3
mov bx,2200h ; bad hack _Demo_
.normalhdma3
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+8],eax
; get pointer #4
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+6]
cmp bx,2118h
je .notnormalhdma4
cmp bx,2119h
je .notnormalhdma4
jmp .normalhdma4
.notnormalhdma4
mov bx,2200h ; bad hack _Demo_
.normalhdma4
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+12],eax
xor ebx,ebx
pop eax
ret
.addrwrite dw 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,0,1,1, 0,1,2,3, 0,1,2,3, 0,1,2,3
dw 0,1,2,3
.addrnumt db 1,2,2,4,4,4,4,4
NEWSYM setuphdma2
push eax
cmp byte[esi+10],0
je near .nohdma
; transfer old address to new address
mov ax,[esi+8]
mov [edx+17],ax
; get address order to be written
xor ebx,ebx
xor eax,eax
xor ecx,ecx
mov al,[esi]
and al,00000111b
mov ah,[.addrnumt+eax]
mov [edx+16],ah
mov bl,al
shl bl,3
add ebx,.addrwrite
mov edi,ebx
; get pointer #1
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi]
cmp bx,2118h
je .notnormalhdma1
cmp bx,2119h
je .notnormalhdma1
jmp .normalhdma1
.notnormalhdma1
mov bx,2200h ; bad hack _Demo_
.normalhdma1
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx],eax
; get pointer #2
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+2]
cmp bx,2118h
je .notnormalhdma2
cmp bx,2119h
je .notnormalhdma2
jmp .normalhdma2
.notnormalhdma2
mov bx,2200h ; bad hack _Demo_
.normalhdma2
shl ebx,2
add ebx,[regptw]
mov eax,[ebx]
mov [edx+4],eax
; get pointer #3
xor ebx,ebx
mov bl,[esi+1] ; PPU memory - 21xx
mov bh,21h
add bx,[edi+4]
cmp bx,2118h
je .notnormalhdma3
cmp bx,2119h
je .notnormalhdma3
jmp .normalhdma3
.notnormalhdma3
mov bx,2200h ; bad hack _Demo_
.normalhdma3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -