⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qsnesdoc.html

📁 SNES game emulator. C and asm files.
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<P><TT>Read # Button&nbsp; Read # Button</TT>
<BR><TT>&nbsp; 1&nbsp;&nbsp;&nbsp; B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
9&nbsp;&nbsp;&nbsp; A</TT>
<BR><TT>&nbsp; 2&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
10&nbsp;&nbsp; X</TT>
<BR><TT>&nbsp; 3&nbsp;&nbsp;&nbsp; Select&nbsp;&nbsp;&nbsp; 11&nbsp;&nbsp;
L (Top-left)</TT>
<BR><TT>&nbsp; 4&nbsp;&nbsp;&nbsp; Start&nbsp;&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp;
R (Top-right)</TT>
<BR><TT>&nbsp; 5&nbsp;&nbsp;&nbsp; Up&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
13&nbsp;&nbsp; -</TT>
<BR><TT>&nbsp; 6&nbsp;&nbsp;&nbsp; Down&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14&nbsp;&nbsp;
-</TT>
<BR><TT>&nbsp; 7&nbsp;&nbsp;&nbsp; Left&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15&nbsp;&nbsp;
-</TT>
<BR><TT>&nbsp; 8&nbsp;&nbsp;&nbsp; Right&nbsp;&nbsp;&nbsp;&nbsp; 16&nbsp;&nbsp;
-</TT>

<P>1 is returned if the button is currently pressed.

<P>If the pattern was similar to that of the NES, reads 17 to 32 would
return the state of joypads 3 and 4.&nbsp; However, zsKnight says that
read #17 returns whether or not the joypad is connected (0 if not connected.)
<BR>&nbsp;
<CENTER><A NAME="RegDMA"></A><FONT SIZE=+2>DMA Registers</FONT></CENTER>

<CENTER>See also <A HREF="#DMATransfers">DMA Transfer Information</A>.</CENTER>
&nbsp;
<BR><A NAME="Reg420B"></A><B><FONT FACE="Lucida Console">Register $420B:
Start DMA transfer (1b/W)</FONT></B>
<PRE>76543210&nbsp; Bits indicate which DMA transfer(s) to initiate
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1=Transfer, 0=Do not transfer)</PRE>
After setting up a DMA transfer, a 1 should be written to the bit corresponding
to the channel you want to use for the transfer.&nbsp; After the 1 is written,
the CPU is paused while the DMA transfer takes place; each byte transferred
takes one clock cycle.&nbsp; Note that a DMA and HDMA transfer cannot be
done on the same channel: if a DMA transfer is initiated while a HDMA channel
is enabled, nothing will happen.

<P><A NAME="Reg420C"></A><B><FONT FACE="Lucida Console">Register $420C:
Enable H-DMA transfer (1b/W)</FONT></B>
<PRE>76543210&nbsp; Bits indicate which HDMA channel(s) to enable
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1=Enable transfers, 0=Disable transfers)</PRE>
After setting up the HDMA transfer(s), a 1 should be written to all the
bits corresponding to the channels you want enabled.&nbsp; Every scanline,
HDMA transfers will occur automatically.

<P><A NAME="Reg43x0"></A><B><FONT FACE="Lucida Console">Register $43?0:
DMA control register (1b/W)</FONT></B>
<PRE>da-fittt&nbsp; d:(DMA only)&nbsp; 0=read from CPU memory, write to $21?? registers
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1=read from $21?? registers, write to CPU memory
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a:(HDMA only) 0=Absolute addressing
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1=Indirect addressing
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i:fixed CPU memory address (1=fixed; 0=inc/dec depending on bit i)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f:0=increment CPU memory pointer by 1 after every read/write 1=decrement
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t:DMA/HDMA transfer type</PRE>
The 'i' and 'f' bits I had mixed up for quite some time... actually they
were backwards in another doc, and so my emu's graphics were screwed for
a long time...&nbsp; Bit 3 means a fixed address, so that the same byte
is transferred every time.
<BR>This register controls the way DMA transfers take place.&nbsp; The
t bits decide the 'mode' of the transfer.&nbsp; To describe how this works,
suppose the bytes of data to be transferred are $01 $23 $45 $67 $89, and
the register to write to is $2118.&nbsp; Assuming f=0 and i=0:
<PRE>Transfer Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Order of transfer
000: 1 reg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $01->$2118 $23->$2118 $45->$2118 $67->$2118 $89->$2118
001: 2 regs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $01->$2118 $23->$211<B>9</B> $45->$2118 $67->$211<B>9</B> $89->$2118
010: 1 reg write twice&nbsp; $01->$2118 $23->$2118 $45->$2118 $67->$2118 $89->$2118
011: 2 regs write twice $01->$2118 $23->$2118 $45->$211<B>9</B> $67->$211<B>9</B> $89->$2118
100: 4 regs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $01->$2118 $23->$211<B>9</B> $45->$211<B>A</B> $67->$211<B>B</B> $89->$2118
101, 110, 111&nbsp; unknown behavior</PRE>
Transfer modes 0 and 2 appear to be the same, but are different in HDMA
mode.&nbsp; I may have modes 0 and 2 backwards (i.e. 0=1 reg write twice.).

<P><A NAME="Reg43x1"></A><B><FONT FACE="Lucida Console">Register $43?1:
DMA Destination Address (1b/W)</FONT></B>
<PRE>bbbbbbbb&nbsp; Add this value to $2100 to get the destination address
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Notice that this restricts what registers you can send to)</PRE>
This is where data will be sent to during a DMA transfer, unless register
$43?0 bit 7 is 1, in which case this will be the source register.&nbsp;
In an HDMA transfer, this is <I>always</I> the source address.

<P><A NAME="Reg43x2"></A><B><FONT FACE="Lucida Console">Register $43?2/$43?3/$43?4:
DMA Source Address (3b/W)</FONT></B>
<PRE>aaaaaaaa aaaaaaaa aaaaaaaa&nbsp; Full 24-bit address of DMA transfer source address</PRE>
This is where data will be read from during a DMA transfer, unless register
$43?0 bit 7 is 1, in which case this will be the destination address.&nbsp;
In an HDMA transfer, this is <I>always</I> the source address, since HDMA
is unidirectional.

<P>Qwertie's horror story: I fixed tons of graphics glitches when I figured
this out:&nbsp; you must increment the value in this register after a DMA
transfer.&nbsp; That is, transferring $10 bytes forward starting at $00E000
would cause this register to be $00E010 afterward.&nbsp; Also, zsKnight
has implied that DMA transfers wrap on a bank boundary; i.e. $43?4 is not
changed during a transfer.

<P><A NAME="Reg43x5"></A><B><FONT FACE="Lucida Console">Register $43?5/$43?6/$43?7:
Bytes to Transfer (2b or 3b/W)</FONT></B>
<PRE>???????? aaaaaaaa aaaaaaaa&nbsp; a: amount of bytes to transfer (DMA only)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In HDMA, purpose is unknown.</PRE>
When using DMA, set this to the number of bytes you want transferred.&nbsp;
Note: if set to 0, 65536 bytes of data will be transferred.&nbsp; I am
not sure whether this register should be set to 0 after the transfer.

<P>In HDMA, it is not neccessary for a SNES programmer to write to this
register.&nbsp; This register probably contains a pointer the next or previous
value written.&nbsp; Based on circumstantial evidence from one game, this
register may contain the value pointer minus one in regular HDMA (e.g.
if this register contained $123456, it would mean that the next value to
be written was contained in $123457.)&nbsp; In indirect HDMA, this register
probably contains the pointer to the value after indirection.

<P>When using regular HDMA, either the bank is copied to this register
or the bank stored here is ignored.&nbsp; In Indirect HDMA, however, the
bank address has to be set manually, and the SNES will automatically determine
the offset.

<P><A NAME="Reg43x8"></A><B><FONT FACE="Lucida Console">Register $43?8/$43?9:
HDMA count pointer (2b/RW?)</FONT></B>

<P>This register does not have to be directly written by the programmer;
the SNES updates it automatically.

<P>I'm calling this register a count pointer because it probably points
to the byte in the HDMA table that contains the count value until the next
segment of the HDMA table is executed.&nbsp; This applies to both HDMA
and Indirect HDMA.&nbsp; (In Indirect HDMA, this register could also be
called the "pointer before indirection".)

<P>Since this is a two and not three-byte register, the bank value should
be taken from <A HREF="#Reg43x2">$43?4</A>.

<P><A NAME="Reg43xA"></A><B><FONT FACE="Lucida Console">Register $43?A:
Scanlines left (1b/RW?)</FONT></B>

<P>This register does not have to be directly written by the programmer.

<P>This register is a countdown that contains the number of scanlines remaining
until the next segment of a HDMA table is executed.&nbsp; When this counter
reaches 0, the pointer contained in <A HREF="#Reg43x8">register $43?8</A>
is advanced to the next count value in the HDMA table, and this register
is loaded with the count value for the next segment of the table.

<P><A NAME="Reg43xA"></A><B><FONT FACE="Lucida Console">Register $2180/$2181/$2182/$2183:
WRAM access (4b/RW)</FONT></B>

<P><TT>$2180&nbsp; dddddddd&nbsp; d: Data byte</TT>
<BR><TT>$2181&nbsp; ???????x xxxxxxxx xxxxxxxx&nbsp; x: address</TT>

<P>This isn't a DMA register at all, but is often used in conjunction with
DMA to do memory-to-memory or memory-fill operations.&nbsp; This is a fairly
simple register, but I'm documenting it here because it's not fully covered
anywhere else.&nbsp; A write or a read to this register causes a read/write
to the specified address, and every time a read/write occurs, the address
part of the register is incremented by one, including the MSB.

<P>Important: The x bits (address) seem to actually form a RAM address,
NOT a CPU address.&nbsp; Therefore, the highest 7 bits of the register
are ignored, since the SNES has only 128 KB of RAM.

<P><A NAME="DMATransfers"></A><FONT SIZE=+3>DMA Transfer Basics</FONT>
<BR>&nbsp;
<BR>First of all, here's a list of DMA (Direct Memory Access) registers:

<P>$43?0: DMA control register
<BR>$43?1: DMA destination register ($21xx)
<BR>$43?2/$43?3/$43?4: DMA source address
<BR>$43?5/$43?6: Number of bytes to transfer
<BR>$420B: Start DMA transfer
<BR>$420C: Enable HDMA transfers

<P>There are 8 DMA channels, numbered 0 to 7.&nbsp; Simply replace the
question mark with the number of the channel you want to use.&nbsp; Each
channel can be used independently of the others.

<P>There are two basic types of DMA: DMA and HDMA.&nbsp; Normal DMA is
quite straightforward. The SNES program simply puts a source address into
$43?2, a destination address into $43?1 and the number of bytes to copy
into $43?5.&nbsp; The reason $43?1 is only a one-byte register is because
the high byte is always $21; e.g. if you set it to $18, the transfer destination
will be $2118.&nbsp; The <A HREF="#Reg43x0">DMA control register</A> controls
how the bytes will be transferred.&nbsp; Using the previous example, setting
it to one(1) will cause bytes written to alternate between $2118 and $2119.&nbsp;
Use $43?0 to start a transfer.&nbsp; For instance, if you were using DMA
channel 1 ($4310, etc.), you would set bit one in that register. (e.g.
LDA #$2 \ STA $420B.)

<P>HDMA is a powerful, and largely undocumented, tool for generating special
effects. It is used often by commercial games and demos alike.&nbsp; Its
most common use is to change one or more of the scroll registers mid-frame;
some games also change the video mode or palette mid-frame with it.&nbsp;
It is set up similar to DMA, except that $43?5 is ignored and probably,
bits 3, 4, 5 and 7 of $43?0 are ignored.

<P><B>Normal HDMA</B>

<P>There are two types of HDMA, controlled by bit 6 of register $43?0.&nbsp;
"Normal" HDMA is the simplest.

<P>The source address register points to an "HDMA table".&nbsp; Such a
table consists of a list of "delay counts" and "write values".&nbsp; For
example, consider the following HDMA table, which is an abridgement of
what I use in my demo QwertEmu.smc.&nbsp; It the destination is the BG1
scroll register.

<P><TT>hdma_table:</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 3 : .dcw 1&nbsp;&nbsp;&nbsp;
; This makes the cool wavey BG effect.</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 4 : .dcw 2</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 6 : .dcw 3</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 7 : .dcw 4</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 6 : .dcw 3</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 4 : .dcw 2</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 3 : .dcw 1</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .dcb 2 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -