www.pudn.com > sn068s.zip > DMA.ASM
; DMA.asm - (H)DMA emulation
;%define NO_WRITES_IN_DMA
;%define LOG_HDMA_WRITES
%define SNEeSe_DMA_asm
%include "misc.ni"
%include "DMA.ni"
%include "cpu/regs.ni"
%include "PPU.ni"
%include "cpumem.ni"
extern In_CPU,HVBJOY
section .text
EXPORT_C DMA_text_start
section .data
EXPORT_C DMA_data_start
section .bss
EXPORT_C DMA_bss_start
section .data
ALIGND
DMA_Data_Areas:
dd TableDMA0,TableDMA1,TableDMA2,TableDMA3
dd TableDMA4,TableDMA5,TableDMA6,TableDMA7
DMA_PPU_Order:
db 0,0,0,0
db 0,1,0,1
db 0,0,0,0
db 0,0,1,1
db 0,1,2,3
db 0,1,0,1
db 0,0,0,0
db 0,0,1,1
HDMA_Size:
db 1,2,2,4
db 4,2,2,4
section .bss
%macro DMA_DATA 1
ALIGNB
TableDMA%1:
; dh0bcttt d=CPU->PPU,h=addr,b=inc/dec,c=inc/fixed,t=type
EXPORT_C DMAP_%1 ,skipb
EXPORT_C BBAD_%1 ; Low byte of 0x21??
EXPORT DMA_Vid_%1 ,skipb
EXPORT NTRL_%1,skipb
DMA_Inc_%1: skipb
EXPORT A1T_%1 ; Source Address L/H/B
EXPORT_C A1TL_%1,skipb ; Source Address L
EXPORT_C A1TH_%1,skipb ; Source Address H
EXPORT_C A1B_%1 ,skipb ; Source Bank Address
skipb
EXPORT DAS_%1 ; Data Size L/H
EXPORT_C DASL_%1,skipb ; Data Size L
EXPORT_C DASH_%1,skipb ; Data Size H
EXPORT_C DASB_%1,skipb ; Data address bank
skipb
EXPORT A2T_%1
EXPORT_C A2L_%1 ,skipb ; HDMA table address L
EXPORT_C A2H_%1 ,skipb ; HDMA table address H
EXPORT_C A2B_%1 ,skipb ; HDMA table bank address
skipb
; DMA_Wr#_x - These hold the write handlers for DMA
; DMA_Rd#_x - These hold the read handlers for DMA
; HDMA_Siz_x - These hold the register size for HDMA
DMA_Wr0_%1: skipl
DMA_Wr1_%1: skipl
DMA_Wr2_%1: skipl
DMA_Wr3_%1: skipl
DMA_Rd0_%1: skipl
DMA_Rd1_%1: skipl
DMA_Rd2_%1: skipl
DMA_Rd3_%1: skipl
DMA_B0_%1: skipl
DMA_B1_%1: skipl
DMA_B2_%1: skipl
DMA_B3_%1: skipl
HDMA_Siz_%1:skipl
%endmacro
DMA_DATA 0
DMA_DATA 1
DMA_DATA 2
DMA_DATA 3
DMA_DATA 4
DMA_DATA 5
DMA_DATA 6
DMA_DATA 7
EXPORT_C MDMAEN,skipb ; DMA enable
EXPORT_C HDMAEN,skipb ; HDMA enable
EXPORT HDMAON,skipb ; HDMA enabled this refresh
; 00dcccaa | d = in DMA/HDMA, if 0 all should be 0
EXPORT In_DMA,skipb ; c = channel # 0-7 | a = address # 0-3
%define DMA_IN_PROGRESS 0x40
section .text
ALIGNC
%if 0
al = data byte
ebx = A-bus address
ebp = DAS (byte count)
esi = Address adjustment
%endif
Do_DMA_Channel:
EXPORT_C Do_DMA_Channel
mov ebx,[edx+A1T] ; CPU address in ebx
and ebx,0x00FFFFFF
xor ebp,ebp
mov bp,[edx+DAS]
dec ebp
and ebp,0xFFFF
inc ebp
;mov ecx,ebp
;shl ecx,3
;add [SNES_Cycles],ecx
mov al,[edx+DMAP]
xor ecx,ecx
movsx esi,byte [edx+DMA_Inc] ; Get address adjustment
test al,al ; Is the operation CPU->PPU?
jns near .ppu_write
; PPU->CPU
mov edi,edx
and eax,byte 7
lea eax,[DMA_PPU_Order+eax*4]
mov cl,[edx+DMA_Vid] ; PPU address in ecx
mov edx,ecx ; PPU address in edx
;add cl,[eax]
mov ecx,[_Read_Map_21+ecx*4]
mov [edi+DMA_Rd0],ecx
mov ecx,edx ; PPU address in ecx
add dl,[eax+1]
mov edx,[_Read_Map_21+edx*4]
mov [edi+DMA_Rd1],edx
mov edx,ecx ; PPU address in edx
add cl,[eax+2]
mov ecx,[_Read_Map_21+ecx*4]
mov [edi+DMA_Rd2],ecx
add dl,[eax+3]
mov edx,[_Read_Map_21+edx*4]
mov [edi+DMA_Rd3],edx
mov edx,edi
cmp ebp,byte 4
jb near .lpr_less_than_4
.loop_ppu_read:
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd0]
%else
call [edx+DMA_Rd0]
SET_BYTE
%endif
.ppu_read_check_0:
add bx,si
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd1]
%else
call [edx+DMA_Rd1]
SET_BYTE
%endif
.ppu_read_check_1:
add bx,si
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd2]
%else
call [edx+DMA_Rd2]
SET_BYTE
%endif
.ppu_read_check_2:
add bx,si
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd3]
%else
call [edx+DMA_Rd3]
SET_BYTE
%endif
.ppu_read_check_3:
add bx,si
sub ebp,byte 4
jz near .ppu_read_done
cmp ebp,byte 4
jnb near .loop_ppu_read
.lpr_less_than_4:
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd0]
%else
call [edx+DMA_Rd0]
SET_BYTE
%endif
.ppu_read_lt4_check_0:
add bx,si
dec ebp
jz near .ppu_read_done
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd1]
%else
call [edx+DMA_Rd1]
SET_BYTE
%endif
.ppu_read_lt4_check_1:
add bx,si
dec ebp
jz .ppu_read_done
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd2]
%else
call [edx+DMA_Rd2]
SET_BYTE
%endif
.ppu_read_lt4_check_2:
add bx,si
dec ebp
jz .ppu_read_done
%ifdef NO_WRITES_IN_DMA
call [edx+DMA_Rd3]
%else
call [edx+DMA_Rd3]
SET_BYTE
%endif
.ppu_read_lt4_check_3:
add bx,si
dec ebp
jnz near .loop_ppu_read
.ppu_read_done:
mov [edx+A1T],bx ; v0.15 forgot to update DMA pointers!
mov word [edx+DAS],0
%ifdef NO_WRITES_IN_DMA
rethere:
%endif
ret
ALIGNC
; CPU->PPU
.ppu_write:
mov edi,edx
and eax,byte 7
lea eax,[DMA_PPU_Order+eax*4]
mov cl,[DMA_Vid+edx] ; PPU address in ecx
mov edx,ecx ; PPU address in edx
;add cl,[eax]
mov ecx,[_Write_Map_21+ecx*4]
mov [edi+DMA_Wr0],ecx
mov ecx,edx ; PPU address in ecx
add dl,[eax+1]
mov edx,[_Write_Map_21+edx*4]
mov [edi+DMA_Wr1],edx
mov edx,ecx ; PPU address in edx
add cl,[eax+2]
mov ecx,[_Write_Map_21+ecx*4]
mov [edi+DMA_Wr2],ecx
add dl,[eax+3]
mov edx,[_Write_Map_21+edx*4]
mov [edi+DMA_Wr3],edx
mov edx,edi
cmp ebp,byte 4
jb near .lpw_less_than_4
.loop_ppu_write:
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr0]
%endif
.ppu_write_check_0:
add bx,si
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr1]
%endif
.ppu_write_check_1:
add bx,si
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr2]
%endif
.ppu_write_check_2:
add bx,si
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr3]
%endif
.ppu_write_check_3:
add bx,si
sub ebp,byte 4
jz near .ppu_write_done
cmp ebp,byte 4
jnb near .loop_ppu_write
.lpw_less_than_4:
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr0]
%endif
.ppu_write_lt4_check_0:
add bx,si
dec ebp
jz near .ppu_write_done
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr1]
%endif
.ppu_write_lt4_check_1:
add bx,si
dec ebp
jz .ppu_write_done
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr2]
%endif
.ppu_write_lt4_check_2:
add bx,si
dec ebp
jz .ppu_write_done
%ifdef NO_WRITES_IN_DMA
GET_BYTE
%else
GET_BYTE
call [edx+DMA_Wr3]
%endif
.ppu_write_lt4_check_3:
add bx,si
dec ebp
jnz near .loop_ppu_write
.ppu_write_done:
mov [edx+A1T],bx ; v0.15 forgot to update DMA pointers!
mov word [edx+DAS],0
.abort_channel:
ret
ALIGNC
EXPORT_C Do_HDMA_Channel
EXPORT Do_HDMA_Channel
mov ebx,[edx+A2T] ; Get table address
and ebx,0x00FFFFFF
mov al,[edx+DMAP] ; Get HDMA control byte
test al,0x40 ; Check for indirect addressing
mov ecx,[edx+HDMA_Siz] ; Get HDMA transfer size
jnz near Do_HDMA_Indirect
Do_HDMA_Absolute:
mov ah,[edx+NTRL] ; Get number of lines to transfer
test ah,0x7F ; Need new set?
jz .Next_Set
test ah,ah
js .Next_Transfer
jmp .Continue
.Next_Set:
GET_BYTE
inc bx ; Adjust table address
test al,al ; Check for zero-length set
mov [edx+NTRL],al ; Save length of set
jz near HDMA_End_Channel
mov [edx+A2T],ebx ; Save new table address
.Next_Transfer:
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
mov bl,[edx+DMA_Vid]
push eax
push ebx
extern _hdma_write__FUcUc
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr0]
cmp cl,2
inc bx ; Adjust temporary table pointer
;jb .End_Transfer
jb near .End_Transfer
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
push eax
mov al,[edx+DMAP]
mov bl,[edx+DMA_Vid]
and eax,byte 7
add bl,[DMA_PPU_Order+eax*4+1]
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr1]
cmp cl,4
inc bx ; Adjust temporary table pointer
;jb .End_Transfer
jb near .End_Transfer
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
push eax
mov al,[edx+DMAP]
mov bl,[edx+DMA_Vid]
and eax,byte 7
add bl,[DMA_PPU_Order+eax*4+2]
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr2]
inc bx
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
push eax
mov al,[edx+DMAP]
mov bl,[edx+DMA_Vid]
and eax,byte 7
add bl,[DMA_PPU_Order+eax*4+3]
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr3]
.End_Transfer:
add [edx+A2T],cx
.Continue:
dec byte [edx+NTRL]
stc
ret
HDMA_End_Channel:
mov [edx+A2T],ebx
clc
ret
Do_HDMA_Indirect:
mov ah,[edx+NTRL] ; Get number of lines to transfer
test ah,0x7F
jz .Next_Set
test ah,ah
js near .Next_Transfer
jmp .Continue
.Next_Set:
GET_BYTE
inc bx
mov [edx+NTRL],al
test al,al
mov ah,al
jz HDMA_End_Channel
GET_BYTE
inc bx
mov [edx+DASL],al
GET_BYTE
inc bx
mov [edx+DASH],al
mov [edx+A2T],ebx
.Next_Transfer:
mov ebx,[edx+DAS]
and ebx,0x00FFFFFF
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
mov bl,[edx+DMA_Vid]
push eax
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr0]
cmp cl,2
inc bx ; Adjust temporary table pointer
;jb .End_Transfer
jb near .End_Transfer
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
push eax
mov al,[edx+DMAP]
mov bl,[edx+DMA_Vid]
and eax,byte 7
add bl,[DMA_PPU_Order+eax*4+1]
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr1]
cmp cl,4
inc bx ; Adjust temporary table pointer
;jb .End_Transfer
jb near .End_Transfer
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
push eax
mov al,[edx+DMAP]
mov bl,[edx+DMA_Vid]
and eax,byte 7
add bl,[DMA_PPU_Order+eax*4+2]
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr2]
inc bx
GET_BYTE
%ifdef LOG_HDMA_WRITES
pusha
push eax
mov al,[edx+DMAP]
mov bl,[edx+DMA_Vid]
and eax,byte 7
add bl,[DMA_PPU_Order+eax*4+3]
push ebx
call _hdma_write__FUcUc
add esp,8
popa
%endif
call [edx+DMA_Wr3]
.End_Transfer:
add [edx+DAS],cx
.Continue:
dec byte [edx+NTRL]
stc
ret
;%1 = num
%macro DMAOPERATION 1
mov al,[_MDMAEN]
test al,1 << (%1)
jz %%no_dma
mov byte [In_DMA],((%1) << 2) | DMA_IN_PROGRESS
LOAD_DMA_TABLE %1
call Do_DMA_Channel
%%no_dma:
%endmacro
ALIGNC
EXPORT SNES_R420B ; MDMAEN
mov al,0
ret
ALIGNC
EXPORT SNES_R420C ; HDMAEN
mov al,[HDMAON]
ret
ALIGNC
EXPORT SNES_W420B ; MDMAEN
mov [_MDMAEN],al
%ifdef NO_DMA
ret
%endif
;mov [SNES_Cycles],R_65c816_Cycles ;
push eax
push ebx
push ecx
push edx
push ebp
push esi
mov al,[In_CPU]
push eax
; Need to save/restore CPU core register set here if in use
mov byte [In_CPU],0
DMAOPERATION 0
DMAOPERATION 1
DMAOPERATION 2
DMAOPERATION 3
DMAOPERATION 4
DMAOPERATION 5
DMAOPERATION 6
DMAOPERATION 7
mov byte [In_DMA],0
pop eax
mov [In_CPU],al
pop esi
pop ebp
pop edx
pop ecx
pop ebx
pop eax
;mov R_65c816_Cycles,[SNES_Cycles] ;
ret
%define CYCLES_PER_DOT 4
%define DOTS_PER_SCANLINE 342
%define DOTS_IN_REFRESH 10
%define DOTS_BEFORE_DISPLAY 22
%define DOTS_BEFORE_REFRESH 128
%define DOTS_IN_DISPLAY 256
%define DOTS_HBLANK_START (DOTS_BEFORE_DISPLAY + DOTS_IN_DISPLAY)
%define CYCLES_NEW_SCANLINE ((DOTS_PER_SCANLINE - DOTS_IN_REFRESH) * CYCLES_PER_DOT)
%define CYCLES_DISPLAY_START (DOTS_BEFORE_DISPLAY * CYCLES_PER_DOT)
%define CYCLES_HBLANK_START ((DOTS_HBLANK_START - DOTS_IN_REFRESH) * CYCLES_PER_DOT)
%define CYCLES_NMI_DELAY 19
%define CYCLES_REFRESH_START (DOTS_BEFORE_REFRESH * CYCLES_PER_DOT)
%define CYCLES_IN_REFRESH (DOTS_IN_REFRESH * CYCLES_PER_DOT)
%define CYCLES_REFRESH_END ((DOTS_BEFORE_REFRESH + DOTS_IN_REFRESH) * CYCLES_PER_DOT)
ALIGNC
EXPORT SNES_W420C ; HDMAEN ; Actually handled within screen core!
%ifdef NO_HDMA
ret
%endif
mov [_HDMAEN],al
;ret
mov [HDMAON],al
ret
test byte [HVBJOY],0x80 ; Vblank?
jnz .in_blank
cmp R_65c816_Cycles,CYCLES_DISPLAY_START ; Hblank?
jb .in_blank
cmp R_65c816_Cycles,CYCLES_HBLANK_START ; Hblank?
;cmp R_65c816_Cycles,1024-40 ; Hblank?
jnb .in_blank
test byte [_INIDISP],0x80 ; Force-blank?
jns .not_in_blank
.in_blank:
%if 0
push eax
push ebx
push ecx
push edx
push ebp
push esi
RELATCH_HDMA_IN_FRAME 0
RELATCH_HDMA_IN_FRAME 1
RELATCH_HDMA_IN_FRAME 2
RELATCH_HDMA_IN_FRAME 3
RELATCH_HDMA_IN_FRAME 4
RELATCH_HDMA_IN_FRAME 5
RELATCH_HDMA_IN_FRAME 6
RELATCH_HDMA_IN_FRAME 7
pop esi
pop ebp
pop edx
pop ecx
pop ebx
pop eax
%endif
mov [HDMAON],al
.not_in_blank:
ret
ALIGNC
EXPORT do_HDMA
mov al,[HDMAON]
test al,al
jz near .no_hdma
push eax
push ebx
push ecx
push edx
push ebp
push esi
push edi
mov al,[In_DMA]
push eax
HDMAOPERATION 0
HDMAOPERATION 1
HDMAOPERATION 2
HDMAOPERATION 3
HDMAOPERATION 4
HDMAOPERATION 5
HDMAOPERATION 6
HDMAOPERATION 7
pop eax
mov [In_DMA],al
pop edi
pop esi
pop ebp
pop edx
pop ecx
pop ebx
pop eax
.no_hdma:
ret
; Requires %eax to be 0x00FFFFFF!
;%1 = num
%macro Reset_DMA_Channel 1
mov [_DMAP_%1],al
mov [_BBAD_%1],al
mov [NTRL_%1],al
mov [A1T_%1],eax
mov [DAS_%1],eax
mov [A2T_%1],eax
push ebx
push ecx
mov ebx,UNSUPPORTED_READ
mov ecx,UNSUPPORTED_WRITE
mov [DMA_Rd0_%1],ebx
mov [DMA_Wr0_%1],ecx
mov [DMA_Rd1_%1],ebx
mov [DMA_Wr1_%1],ecx
mov [DMA_Rd2_%1],ebx
mov [DMA_Wr2_%1],ecx
mov [DMA_Rd3_%1],ebx
mov [DMA_Wr3_%1],ecx
pop ecx
pop ebx
mov byte [DMA_Inc_%1],0
%endmacro
EXPORT Reset_DMA
; Set eax to 0...
xor eax,eax
mov [_MDMAEN],al
mov [_HDMAEN],al
mov [HDMAON],al
mov [In_DMA],al
; Now 0x00FFFFFF...
mov eax,0x00FFFFFF
Reset_DMA_Channel 0
Reset_DMA_Channel 1
Reset_DMA_Channel 2
Reset_DMA_Channel 3
Reset_DMA_Channel 4
Reset_DMA_Channel 5
Reset_DMA_Channel 6
Reset_DMA_Channel 7
; Back to 0...
xor eax,eax
ret
ALIGNC
EXPORT_C Update_DMA_PPU_Handlers
EXPORT Update_DMA_PPU_Handlers
cmp byte [In_DMA],0
jz near Update_DMA_PPU_Handlers_Specific.not_in_dma
movzx edi,byte [In_DMA]
and edi,(7 << 2)
Update_DMA_PPU_Handlers_Specific:
push eax
push ebx
push ecx
push edx
mov edi,[DMA_Data_Areas+edi]
xor ecx,ecx
mov al,[edi+DMAP]
and eax,byte 7
mov cl,[edi+DMA_Vid] ; PPU address in ecx
mov dl,[HDMA_Size+eax]
lea eax,[DMA_PPU_Order+eax*4]
mov [edi+HDMA_Siz],dl
mov edx,ecx ; PPU address in edx
;add cl,[eax]
mov ebx,[_Read_Map_21+ecx*4]
mov ecx,[_Write_Map_21+ecx*4]
mov [edi+DMA_Rd0],ebx
mov [edi+DMA_Wr0],ecx
mov ecx,edx ; PPU address in ecx
add dl,[eax+1]
mov ebx,[_Read_Map_21+edx*4]
mov edx,[_Write_Map_21+edx*4]
mov [edi+DMA_Rd1],ebx
mov [edi+DMA_Wr1],edx
mov edx,ecx ; PPU address in edx
add cl,[eax+2]
mov ebx,[_Read_Map_21+ecx*4]
mov ecx,[_Write_Map_21+ecx*4]
mov [edi+DMA_Rd2],ebx
mov [edi+DMA_Wr2],ecx
add dl,[eax+3]
mov ebx,[_Read_Map_21+edx*4]
mov edx,[_Write_Map_21+edx*4]
mov [edi+DMA_Rd3],ebx
mov [edi+DMA_Wr3],edx
pop edx
pop ecx
pop ebx
pop eax
.not_in_dma:
ret
; Read from 43xx handlers
;%1 = num
%macro MAP_READ_DMA 1
ALIGNC
EXPORT MAP_READ_DMAP%1
mov al,[_DMAP_%1]
ret
ALIGNC
EXPORT MAP_READ_BBAD%1
mov al,[_BBAD_%1]
ret
ALIGNC
EXPORT MAP_READ_A1TL%1
mov al,[_A1TL_%1]
ret
ALIGNC
EXPORT MAP_READ_A1TH%1
mov al,[_A1TH_%1]
ret
ALIGNC
EXPORT MAP_READ_A1B%1
mov al,[_A1B_%1]
ret
ALIGNC
EXPORT MAP_READ_DASL%1
mov al,[_DASL_%1]
ret
ALIGNC
EXPORT MAP_READ_DASH%1
mov al,[_DASH_%1]
ret
ALIGNC
EXPORT MAP_READ_DASB%1
mov al,[_DASB_%1]
ret
ALIGNC
EXPORT MAP_READ_A2L%1
mov al,[_A2L_%1]
ret
ALIGNC
EXPORT MAP_READ_A2H%1
mov al,[_A2H_%1]
ret
ALIGNC
EXPORT MAP_READ_NTRL%1
mov al,[NTRL_%1]
ret
%endmacro
MAP_READ_DMA 0
MAP_READ_DMA 1
MAP_READ_DMA 2
MAP_READ_DMA 3
MAP_READ_DMA 4
MAP_READ_DMA 5
MAP_READ_DMA 6
MAP_READ_DMA 7
; Write to 43xx handlers
;%1 = num
%macro MAP_WRITE_DMA 1
ALIGNC
EXPORT MAP_WRITE_DMAP%1
cmp [_DMAP_%1],al
je .no_change
push ebx
mov [_DMAP_%1],al
test al,8 ; Does the operation require address adjustment?
mov bl,0
jnz .set_adjustment
dec ebx ; Set address decrement
test al,0x10
jnz .set_adjustment
add bl,2 ; Set address increment
.set_adjustment:
mov [DMA_Inc_%1],bl
pop ebx
shr edi,2
and edi,byte 7*4
jmp Update_DMA_PPU_Handlers_Specific ; It'll return for us
.no_change:
ret
ALIGNC
EXPORT MAP_WRITE_BBAD%1
cmp [_DMAP_%1],al
je .no_change
mov [_BBAD_%1],al
shr edi,2
and edi,byte 7*4
jmp Update_DMA_PPU_Handlers_Specific ; It'll return for us
.no_change:
ret
ALIGNC
EXPORT MAP_WRITE_A1TL%1
mov [_A1TL_%1],al
ret
ALIGNC
EXPORT MAP_WRITE_A1TH%1
mov [_A1TH_%1],al
ret
ALIGNC
EXPORT MAP_WRITE_A1B%1
cmp [_A1B_%1],al
je .no_change
mov [_A1B_%1],al
mov [_A2B_%1],al
.no_change:
ret
ALIGNC
EXPORT MAP_WRITE_DASL%1
mov [_DASL_%1],al
ret
ALIGNC
EXPORT MAP_WRITE_DASH%1
mov [_DASH_%1],al
ret
ALIGNC
EXPORT MAP_WRITE_DASB%1
cmp [_DASB_%1],al
je .no_change
mov [_DASB_%1],al
.no_change:
ret
ALIGNC
EXPORT MAP_WRITE_A2L%1
mov [_A2L_%1],al
ret
ALIGNC
EXPORT MAP_WRITE_A2H%1
mov [_A2H_%1],al
ret
ALIGNC
EXPORT MAP_WRITE_NTRL%1
mov [NTRL_%1],al
ret
%endmacro
MAP_WRITE_DMA 0
MAP_WRITE_DMA 1
MAP_WRITE_DMA 2
MAP_WRITE_DMA 3
MAP_WRITE_DMA 4
MAP_WRITE_DMA 5
MAP_WRITE_DMA 6
MAP_WRITE_DMA 7
section .text
ALIGNC
section .data
ALIGND
section .bss
ALIGNB