Как изменить положение спрайта с помощью сборки 65c816 для SNES? - PullRequest
0 голосов
/ 08 февраля 2019

Я пытаюсь изменить позицию своего спрайта, но не могу понять, как

Я часами искал ответы, но ни один из них не работает с ассемблером, который я использую: WLA-DX .Я чрезвычайно новичок в сборке 6502, так что прости меня, если моя логика действительно искажена.Я следовал учебнику по учебнику georgjz по GitHub.Мой спрайт - это просто один цветной квадрат, а поддон - это поддон по умолчанию, который поставляется с 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

Я пытаюсь по крайней мере заставить спрайт переместиться вправо на 1 пиксель за кадр, но спрайт вообще не двигается

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

Редактировать: я добавил код из комментария @Michael, и ничего не имеетизменилось.Вот код, который я обновил:

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

, и я добавил подпрограмму MoveSprite после CGRAMLoop

1 Ответ

0 голосов
/ 08 февраля 2019

Я не вижу кода, который на самом деле изменит позицию вашего спрайта.

Но скажем, у вас есть переменная 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
...