Help us understand the problem. What is going on with this article?

WLA DXを使ってスーパーファミコンROMのアセンブラをコンパイルする_HelloWorld

More than 1 year has passed since last update.

下記URLを参考にしたけど、それぞれのコマンドの意味等々を日本語でメモしておく。実行環境はmacOS X。WLA DXというものを使うと、開発がちょっと楽になるらしい。

参考URL

WLA DXのインストール

WLA DXとは

GitHubリポジトリ

WLA DXはマクロアセンブラであり、GB-Z80、Z80、6502、65c02、6510、65816、HuC6280、SPC-700等のCPUをプログラムできます。パッケージは GB-Z80逆アセンブラといくつかのコンバータを含んでいます。WLA DXは当初、ゲームボーイ用 ROMイメージへコンパイルするようプログラムされていましたが、しかし今日ではコードの入った既存ROMイメージにパッチを当てることもでき、NES-6502、C64-6510、SNESの SPC-700のような他 CPU用にプログラムファイルや ROMファイルをコンパイルすることさえできます。

とのこと。

SNES研究室というサイトでも、取り上げられていた。

全体コマンド

brew install cmake
git clone git@github.com:vhelin/wla-dx.git
cmake -G Unix\ Makefiles ./wla-dx/
make
make install
wla-65816

各コマンドの意味

  1. CMakeをインストールする。CMakeとは

    brew install cmake
    
  2. WLA DXのソースをGitHubからクローンして取得する

    git clone git@github.com:vhelin/wla-dx.git
    
  3. CMakeのプロジェクトファイルの形式を指定する、参考記事は下記だったんだが、動かなかったのでここは自分で変えた

    cmake -G “Unix Makefiles” .
    下記に変更
    cmake -G Unix\ Makefiles ./wla-dx/
    
  4. CMakeで作成されたMakefileを基にしてソースコードをコンパイルする

    make
    
  5. makeで生成された生成物をディレクトリにコピーしインストールする

    make install
    
  6. WLA DXのインストールが成功しているかコマンドを実行してみて確認する

    wla-65816
    

Header.incを作成

ここから取得

コード本体

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 Tile Demo       "  ; 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を作成

ここから取得

コード本体

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     #$30    ; 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

HelloWorld(helloworld.asm)本体を作成

helloworld.asm
; SNES Initialization Tutorial code
; This code is in the public domain.

 .include "Header.inc"
 .include "Snes_Init.asm"

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

 .bank 0
 .section "MainCode"

 Start:
     ; Initialize the SNES.
     Snes_Init

     ; Set the background color to green.
     sep     #$20        ; Set the A register to 8-bit.
     lda     #%10000000  ; Force VBlank by turning off the screen.
     sta     $2100
     lda     #%11100000  ; Load the low byte of the green color.
     sta     $2122
     lda     #%00000000  ; Load the high byte of the green color.
     sta     $2122
     lda     #%00001111  ; End VBlank, setting brightness to 15 (100%).
     sta     $2100

     ; Loop forever.
 Forever:
     jmp Forever

 .ends

コンパイルする(helloworld.o)

wla-65816 -v helloworld.asm

helloworld.oが出力される。

リンカ(helloworld.link)を作成する

helloworld.link
[objects]
helloworld.o

ROMファイルにパッケージする(helloworld.smc)

wlalink -v helloworld.link helloworld.smc

helloworld.smcが作成される。エミュレータで実行すれば、画面いっぱいに緑色の画面が出るはず。

参考記事の著者のGitHubリポジトリ

上述の内容がまとめられている、GitHubリポジトリ

その他

アセンブラの$と%について

$は16進数、%は2進数を示す。

$10 = %10000 = 16
$FF = %11111111 = 255

いろいろな参考サイト

mediado
私たちメディアドゥは、電子書籍を読者に届けるために「テクノロジー」で「出版社」と「電子書店」を繋ぎ、その先にいる作家と読者を繋げる「電子書籍取次」事業を展開しております。業界最多のコンテンツラインナップとともに最新のテクノロジーを駆使した各種ソリューションを出版社や電子書店に提供し、グローバル且つマルチコンテンツ配信プラットフォームを目指しています。
https://mediado.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away