forked from sonicretro/skdisasm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsonic3k.macros.asm
154 lines (132 loc) · 4.64 KB
/
sonic3k.macros.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
; simplifying macros and functions
; nameless temporary symbols should NOT be used inside macros because they can interfere with the surrounding code
; normal labels should be used instead (which automatically become local to the macro)
; makes a VDP command
vdpComm function addr,type,rwd,(((type&rwd)&3)<<30)|((addr&$3FFF)<<16)|(((type&rwd)&$FC)<<2)|((addr&$C000)>>14)
; values for the type argument
VRAM = %100001
CRAM = %101011
VSRAM = %100101
; values for the rwd argument
READ = %001100
WRITE = %000111
DMA = %100111
; tells the VDP to copy a region of 68k memory to VRAM or CRAM or VSRAM
dma68kToVDP macro source,dest,length,type
lea (VDP_control_port).l,a5
move.l #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5)
move.l #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5)
move.w #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5)
move.w #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5)
move.w #(vdpComm(dest,type,DMA)&$FFFF),(DMA_trigger_word).w
move.w (DMA_trigger_word).w,(a5)
; From ' § 7 DMA TRANSFER' of https://emu-docs.org/Genesis/sega2f.htm:
;
; "In the case of ROM to VRAM transfers,
; a hardware feature causes occasional failure of DMA unless the
; following two conditions are observed:
;
; --The destination address write (to address $C00004) must be a word
; write.
;
; --The final write must use the work RAM.
; There are two ways to accomplish this, by copying the DMA program
; into RAM or by doing a final "move.w ram address $C00004""
endm
; tells the VDP to fill a region of VRAM with a certain byte
dmaFillVRAM macro byte,addr,length
lea (VDP_control_port).l,a5
move.w #$8F01,(a5) ; VRAM pointer increment: $0001
move.l #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ...
move.w #$9780,(a5) ; VRAM fill
move.l #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ...
move.w #(byte)<<8,(VDP_data_port).l ; Fill with byte
loop: move.w (a5),d1
btst #1,d1
bne.s loop ; busy loop until the VDP is finished filling...
move.w #$8F02,(a5) ; VRAM pointer increment: $0002
endm
; calculates initial loop counter value for a dbf loop
; that writes n bytes total at 4 bytes per iteration
bytesToLcnt function n,n>>2-1
; calculates initial loop counter value for a dbf loop
; that writes n bytes total at 2 bytes per iteration
bytesToWcnt function n,n>>1-1
; calculates initial loop counter value for a dbf loop
; that writes n bytes total at x bytes per iteration
bytesToXcnt function n,x,n/x-1
; fills a region of 68k RAM with 0
clearRAM macro addr,length
if ((addr)&$8000)==0
lea (addr).l,a1
else
lea (addr).w,a1
endif
moveq #0,d0
if ((addr)&1)
move.b d0,(a1)+
endif
move.w #bytesToLcnt(length - ((addr)&1)),d1
.loop: move.l d0,(a1)+
dbf d1,.loop
if ((length - ((addr)&1))&2)
move.w d0,(a1)+
endif
if ((length - ((addr)&1))&1)
move.b d0,(a1)+
endif
endm
; tells the Z80 to stop, and waits for it to finish stopping (acquire bus)
stopZ80 macro
move.w #$100,(Z80_bus_request).l ; stop the Z80
loop: btst #0,(Z80_bus_request).l
bne.s loop ; loop until it says it's stopped
endm
; tells the Z80 to start again
startZ80 macro
move.w #0,(Z80_bus_request).l ; start the Z80
endm
; function to make a little-endian 16-bit pointer for the Z80 sound driver
z80_ptr function x,(x)<<8&$FF00|(x)>>8&$7F|$80
; macro to declare a little-endian 16-bit pointer for the Z80 sound driver
rom_ptr_z80 macro addr
dc.w z80_ptr(addr)
endm
; macros to convert from tile index to art tiles, block mapping or VRAM address.
make_art_tile function addr,pal,pri,((pri&1)<<15)|((pal&3)<<13)|(addr&tile_mask)
tiles_to_bytes function addr,((addr&$7FF)<<5)
; function to calculate the location of a tile in plane mappings with a width of 40 cells
planeLocH28 function col,line,(($50 * line) + (2 * col))
; macro for generating level select strings
levselstr macro str
save
codepage LEVELSELECT
dc.b strlen(str)-1, str
restore
endm
; macros for defining animated PLC script lists
zoneanimstart macro {INTLABEL}
__LABEL__ label *
zoneanimcount := 0
zoneanimcur := "__LABEL__"
dc.w zoneanimcount___LABEL__ ; Number of scripts for a zone (-1)
endm
zoneanimend macro
zoneanimcount_{"\{zoneanimcur}"} = zoneanimcount-1
endm
zoneanimdeclanonid := 0
zoneanimdecl macro duration,artaddr,vramaddr,numentries,numvramtiles
zoneanimdeclanonid := zoneanimdeclanonid + 1
start:
dc.l (duration&$FF)<<24|artaddr
dc.w tiles_to_bytes(vramaddr)
dc.b numentries, numvramtiles
zoneanimcount := zoneanimcount + 1
endm
tribyte macro val
if "val"<>""
dc.b (val >> 16)&$FF,(val>>8)&$FF,val&$FF
shift
tribyte ALLARGS
endif
endm