1

I am trying to modify my sprite's position, but I can't figure out how to

I have spent hours searching for answers, but none of which work with the assembler I am using: WLA-DX. I am extremely new to 6502 assembly, so forgive me if my logic is really skewed. I was following the tutorial on georgjz's tutorial on GitHub. My sprite is just a single colored square and the pallet is the default pallet that comes with yy-chr

Header.inc

;==LoRom==      ; We'll get to HiRom some other time.

.MEMORYMAP                      ; Begin describing the system architecture.
  SLOTSIZE $8000                ; The slot is $8000 bytes in size. More details on slots later.
  DEFAULTSLOT 0
  SLOT 0 $8000                  ; Defines Slot 0's starting address.
.ENDME          ; End MemoryMap definition

.ROMBANKSIZE $8000              ; Every ROM bank is 32 KBytes in size
.ROMBANKS 8                     ; 2 Mbits - Tell WLA we want to use 8 ROM Banks

.SNESHEADER
  ID "SNES"                     ; 1-4 letter string, just leave it as "SNES"

  NAME "SNES Testing         "  ; Program Title - can't be over 21 bytes,
  ;    "123456789012345678901"  ; use spaces for unused bytes of the name.

  SLOWROM
  LOROM

  CARTRIDGETYPE $00             ; $00 = ROM only, see WLA documentation for others
  ROMSIZE $08                   ; $08 = 2 Mbits,  see WLA doc for more..
  SRAMSIZE $00                  ; No SRAM         see WLA doc for more..
  COUNTRY $01                   ; $01 = U.S.  $00 = Japan  $02 = Australia, Europe, Oceania and Asia  $03 = Sweden  $04 = Finland  $05 = Denmark  $06 = France  $07 = Holland  $08 = Spain  $09 = Germany, Austria and Switzerland  $0A = Italy  $0B = Hong Kong and China  $0C = Indonesia  $0D = Korea
  LICENSEECODE $00              ; Just use $00
  VERSION $00                   ; $00 = 1.00, $01 = 1.01, etc.
.ENDSNES

.SNESNATIVEVECTOR               ; Define Native Mode interrupt vector table
  COP EmptyHandler
  BRK EmptyHandler
  ABORT EmptyHandler
  NMI VBlank
  IRQ EmptyHandler
.ENDNATIVEVECTOR

.SNESEMUVECTOR                  ; Define Emulation Mode interrupt vector table
  COP EmptyHandler
  ABORT EmptyHandler
  NMI EmptyHandler
  RESET Start                   ; where execution starts
  IRQBRK EmptyHandler
.ENDEMUVECTOR

.BANK 0 SLOT 0                  ; Defines the ROM bank and the slot it is inserted in memory.
.ORG 0                          ; .ORG 0 is really $8000, because the slot starts at $8000
.SECTION "EmptyVectors" SEMIFREE

EmptyHandler:
       rti

.ENDS

.EMPTYFILL $00                  ; fill unused areas with $00, opcode for BRK.  
                                ; BRK will crash the snes if executed.

Snes_Init.asm

.MACRO Snes_Init
    sei         ; Disabled interrupts
    clc         ; clear carry to switch to native mode
    xce         ; Xchange carry & emulation bit. native mode
    rep     #$18    ; Binary mode (decimal mode off), X/Y 16 bit
         ldx    #$1FFF  ; set stack to $1FFF
         txs

         jsr Init
 .ENDM

 .bank 0
 .section "Snes_Init" SEMIFREE
 Init:
    sep     #$20    ; X,Y,A are 8 bit numbers
    lda     #$8F    ; screen off, full brightness
    sta     $2100   ; brightness + screen enable register 
    stz     $2101   ; Sprite register (size + address in VRAM) 
    stz     $2102   ; Sprite registers (address of sprite memory [OAM])
    stz     $2103   ;    ""                       ""
    stz     $2105   ; Mode 0, = Graphic mode register
    stz     $2106   ; noplanes, no mosaic, = Mosaic register
    stz     $2107   ; Plane 0 map VRAM location
    stz     $2108   ; Plane 1 map VRAM location
    stz     $2109   ; Plane 2 map VRAM location
    stz     $210A   ; Plane 3 map VRAM location
    stz     $210B   ; Plane 0+1 Tile data location
    stz     $210C   ; Plane 2+3 Tile data location
    stz     $210D   ; Plane 0 scroll x (first 8 bits)
    stz     $210D   ; Plane 0 scroll x (last 3 bits) #$0 - #$07ff
    lda     #$FF    ; The top pixel drawn on the screen isn't the top one in the tilemap, it's the one above that.
    sta     $210E   ; Plane 0 scroll y (first 8 bits)
    sta     $2110   ; Plane 1 scroll y (first 8 bits)
    sta     $2112   ; Plane 2 scroll y (first 8 bits)
    sta     $2114   ; Plane 3 scroll y (first 8 bits)
    lda     #$07    ; Since this could get quite annoying, it's better to edit the scrolling registers to fix this.
    sta     $210E   ; Plane 0 scroll y (last 3 bits) #$0 - #$07ff
    sta     $2110   ; Plane 1 scroll y (last 3 bits) #$0 - #$07ff
    sta     $2112   ; Plane 2 scroll y (last 3 bits) #$0 - #$07ff
    sta     $2114   ; Plane 3 scroll y (last 3 bits) #$0 - #$07ff
    stz     $210F   ; Plane 1 scroll x (first 8 bits)
    stz     $210F   ; Plane 1 scroll x (last 3 bits) #$0 - #$07ff
    stz     $2111   ; Plane 2 scroll x (first 8 bits)
    stz     $2111   ; Plane 2 scroll x (last 3 bits) #$0 - #$07ff
    stz     $2113   ; Plane 3 scroll x (first 8 bits)
    stz     $2113   ; Plane 3 scroll x (last 3 bits) #$0 - #$07ff
    lda     #$80    ; increase VRAM address after writing to $2119
    sta     $2115   ; VRAM address increment register
    stz     $2116   ; VRAM address low
    stz     $2117   ; VRAM address high
    stz     $211A   ; Initial Mode 7 setting register
    stz     $211B   ; Mode 7 matrix parameter A register (low)
    lda     #$01
    sta     $211B   ; Mode 7 matrix parameter A register (high)
    stz     $211C   ; Mode 7 matrix parameter B register (low)
    stz     $211C   ; Mode 7 matrix parameter B register (high)
    stz     $211D   ; Mode 7 matrix parameter C register (low)
    stz     $211D   ; Mode 7 matrix parameter C register (high)
    stz     $211E   ; Mode 7 matrix parameter D register (low)
    sta     $211E   ; Mode 7 matrix parameter D register (high)
    stz     $211F   ; Mode 7 center position X register (low)
    stz     $211F   ; Mode 7 center position X register (high)
    stz     $2120   ; Mode 7 center position Y register (low)
    stz     $2120   ; Mode 7 center position Y register (high)
    stz     $2121   ; Color number register ($0-ff)
    stz     $2123   ; BG1 & BG2 Window mask setting register
    stz     $2124   ; BG3 & BG4 Window mask setting register
    stz     $2125   ; OBJ & Color Window mask setting register
    stz     $2126   ; Window 1 left position register
    stz     $2127   ; Window 2 left position register
    stz     $2128   ; Window 3 left position register
    stz     $2129   ; Window 4 left position register
    stz     $212A   ; BG1, BG2, BG3, BG4 Window Logic register
    stz     $212B   ; OBJ, Color Window Logic Register (or,and,xor,xnor)
    sta     $212C   ; Main Screen designation (planes, sprites enable)
    stz     $212D   ; Sub Screen designation
    stz     $212E   ; Window mask for Main Screen
    stz     $212F   ; Window mask for Sub Screen
    lda     #$30
    sta     $2130   ; Color addition & screen addition init setting
    stz     $2131   ; Add/Sub sub designation for screen, sprite, color
    lda     #$E0
    sta     $2132   ; color data for addition/subtraction
    stz     $2133   ; Screen setting (interlace x,y/enable SFX data)
    stz     $4200   ; Enable V-blank, interrupt, Joypad register
    lda     #$FF
    sta     $4201   ; Programmable I/O port
    stz     $4202   ; Multiplicand A
    stz     $4203   ; Multiplier B
    stz     $4204   ; Multiplier C
    stz     $4205   ; Multiplicand C
    stz     $4206   ; Divisor B
    stz     $4207   ; Horizontal Count Timer
    stz     $4208   ; Horizontal Count Timer MSB (most significant bit)
    stz     $4209   ; Vertical Count Timer
    stz     $420A   ; Vertical Count Timer MSB
    stz     $420B   ; General DMA enable (bits 0-7)
    stz     $420C   ; Horizontal DMA (HDMA) enable (bits 0-7)
    stz     $420D   ; Access cycle designation (slow/fast rom)
    cli         ; Enable interrupts
    rts
 .ends

Testing.asm

.include "header.inc"
.include "Snes_Init.asm"

SpriteData: .incbin "sprite.sprite"
ColorData: .incbin "sprite.pal"

VBlank:    ; Needed to satisfy interrupt definition in "Header.inc"
    RTI

Start:
    Snes_Init
    sei                     ; disable interrupts
    clc                     ; clear the carry flag
    xce                     ; switch the 65816 to native (16-bit mode)
    lda #$8f                ; force v-blanking
    sta $2100
    stz $4200            ; disable NMI

    ; transfer VRAM data
    stz $2116              ; set the VRAM address to $0000
    stz $2117
    lda #$80
    sta $2115              ; increment VRAM address by 1 when writing to $2119
    ldx #$00                ; set register X to zero, we will use X as a loop counter and offset

VRAMLoop:
    .16BIT
    lda SpriteData, X       ; get bitplane 0/2 byte from the sprite data
    sta $2118             ; write the byte in A to VRAM
    sta $0000             ; write the byte in A to VRAM
    inx                     ; increment counter/offset
    lda SpriteData, X       ; get bitplane 1/3 byte from the sprite data
    sta $2119             ; write the byte in A to VRAM
    sta $0000             ; write the byte in A to VRAM
    inx                     ; increment counter/offset
    cpx #$20                ; check whether we have written $04 * $20 : $80 bytes to VRAM (four sprites)
    bcc VRAMLoop            ; if X is smaller than $80, continue the loop

    ; transfer CGRAM data
    lda #$80
    sta $2121               ; set CGRAM address to $80
    ldx #$00                ; set X to zero, use it as loop counter and offset

CGRAMLoop:
    lda ColorData, X        ; get the color low byte
    sta $2122              ; store it in CGRAM
    inx                     ; increase counter/offset
    lda ColorData, X        ; get the color high byte
    sta $2122              ; store it in CGRAM
    inx                     ; increase counter/offset
    cpx #$20                ; check whether 32/$20 bytes were transfered
    bcc CGRAMLoop           ; if not, continue loop

    stz $2102             ; set the OAM address to ...
    stz $2103             ; ...at $0000

    ; OAM data for first sprite
    lda #$78      ; horizontal position of first sprite
    sta $2104
    lda #$68       ; vertical position of first sprite
    sta $2104
    lda #$00                ; name of first sprite
    sta $2104
    lda #$00                ; no flip, prio 0, palette 0
    sta $2104

    ; make Objects visible
    lda #$10
    sta $212C
    ; release forced blanking, set screen to full brightness
    lda #$0f
    sta $2100
    jmp GameLoop            ; all initialization is done

GameLoop:
    wai                     ; wait for NMI / V-Blank
    jmp GameLoop

I am trying to at least get the sprite to move to the right 1 pixel per frame, but the sprite isn't moving at all

===========================================================================

Edit: I added the code from the comment by @Michael, and nothing has changed. Here is the code that I updated:

Snes_Init.asm

 .define SpriteX $00A0
 Init:
    sep     #$20    ; X,Y,A are 8 bit numbers
    lda     #$78
    sta     SpriteX
    ;Initialization code
    rts
.ends

Testing.asm

VBlank:    ; Needed to satisfy interrupt definition in "Header.inc"
    jsr MoveSprite
    RTI

; Code

CGRAMLoop:
    ;More code

    ; OAM data for first sprite
    lda SpriteX      ; horizontal position of first sprite
    sta $2104
    lda #$68       ; vertical position of first sprite
    sta $2104
    lda #$00                ; name of first sprite
    sta $2104
    lda #$00                ; no flip, prio 0, palette 0
    sta $2104

    ;Even more code

and I added the MoveSprite subroutine after CGRAMLoop

4

1 回答 1

0

我没有看到任何实际上会改变你的精灵位置的代码。

但是,假设您有一个 zeropage 变量,用于存储当前 X 位置:

.define spriteX  $00A0  ; I used address $A0 as an example. Just pick some address
                        ; that you aren't already using for something else

在初始化期间的某个地方,你给它一些初始值:

sep #$20
lda #$78
sta spriteX

然后你可以编写一个增加值并将其写入 OAM 的子例程:

MoveSprite:
    php
    sep #$20
    stz $2102
    stz $2103 
    inc spriteX
    lda spriteX
    sta $2104
    lda #$68                            
    sta $2104  ; This write is necessary even if you're not changing the Y position,
               ; because there's some internal latching going on in the PPU.
    plp
    rts

然后你可以从你的VBlank中断处理程序中调用那个子程序。
请注意,您可能需要一个额外的计数器来仅每隔一帧(或您喜欢的任何间隔)增加位置;否则精灵会很快滚动。


您还需要启用 VBlank NMI 才能实际触发中断:

lda #$80
sta $4200        ; Enable VBlank NMI

jmp GameLoop     ; all initialization is done
于 2019-02-08T20:55:14.103 回答