Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added nesasm lexer #1354

Merged
merged 13 commits into from Nov 12, 2019
11 changes: 11 additions & 0 deletions lib/rouge/demos/nesasm
@@ -0,0 +1,11 @@
.bank 0
.org $C000
Reset:
jsr WaitSync ; wait for VSYNC
jsr ClearRAM ; clear RAM
jsr WaitSync ; wait for VSYNC (and PPU warmup)

lda #$3f ; $3F -> A register
ldy #$00 ; $00 -> Y register
sta PPU_ADDR ; write #HIGH byte first
sty PPU_ADDR ; $3F00 -> PPU address
74 changes: 74 additions & 0 deletions lib/rouge/lexers/nesasm.rb
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
module Lexers
class NesAsm < RegexLexer
title "NesAsm"
desc "Nesasm3 assembly (6502 asm)"
tag 'nesasm'
aliases 'nes'
filenames '*.nesasm'

def self.keywords
@keywords ||= %w(
ADC AND ASL BIT BRK CMP CPX CPY DEC EOR INC JMP JSR LDA LDX LDY LSR
NOP ORA ROL ROR RTI RTS SBC STA STX STY TAX TXA DEX INX TAY TYA DEY
INY BPL BMI BVC BVS BCC BCS BNE BEQ CLC SEC CLI SEI CLV CLD SED TXS
TSX PHA PLA PHP PLP
)
end

def self.keywords_type
@keywords_type ||= %w(
DB DW BYTE WORD
)
end

def self.keywords_reserved
@keywords_reserved ||= %w(
INCBIN INCLUDE ORG BANK RSSET RS MACRO ENDM DS PROC ENDP PROCGROUP
ENDPROCGROUP INCCHR DEFCHR ZP BSS CODE DATA IF IFDEF IFNDEF ELSE
ENDIF FAIL INESPRG INESCHR INESMAP INESMIR
)
end

state :root do
rule %r/\s+/m, Text
rule %r(;.*), Comment::Single

rule %r/[\(\)\,\.\[\]]/, Punctuation
rule %r/\#?\%[0-1]+/, Num::Bin # #%00110011 %00110011
ShyDev marked this conversation as resolved.
Show resolved Hide resolved
rule %r/\#?\$\h+/, Num::Hex # $1f #$1f
rule %r/\#?\d+/, Num # 10 #10
rule %r([~&*+=\|?:<>/-]), Operator

rule %r/\#?\w+:?/i do |m|
ShyDev marked this conversation as resolved.
Show resolved Hide resolved
name = m[0].upcase

if self.class.keywords.include? name
token Keyword
elsif self.class.keywords_type.include? name
token Keyword::Type
elsif self.class.keywords_reserved.include? name
token Keyword::Reserved
else
token Name::Function
end
end

rule %r/\#?(?:LOW|HIGH)\(.*\)/i, Keyword::Reserved # LOW() #HIGH()

rule %r/\#\(/, Punctuation # #()

rule %r/"/, Str, :string
ShyDev marked this conversation as resolved.
Show resolved Hide resolved
end

state :string do
rule %r/"/, Str, :pop!
rule %r/\\"?/, Str
pyrmont marked this conversation as resolved.
Show resolved Hide resolved
rule %r/[^"\\]+/m, Str
end
end
end
end
14 changes: 14 additions & 0 deletions spec/lexers/nesasm_spec.rb
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

describe Rouge::Lexers::NesAsm do
let(:subject) { Rouge::Lexers::NesAsm.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'foo.nesasm'
end
end
end
51 changes: 51 additions & 0 deletions spec/visual/samples/nesasm
@@ -0,0 +1,51 @@
.inesprg 2 ; 2x 16KB PRG code banks
.ineschr 1 ; 1x 8KB CHR data banks
.inesmap 0 ; mapper (0 = NROM), no bank swapping
.inesmir 0 ; 0 = horizontal background mirroring (for vertical scrolling)

;;;;;; VARIABLES
.rsset $0000 ; zero page

gamestate .rs 1
playerx .rs 2

.bank 1
.org $C000

Reset:
jsr WaitSync ; wait for VSYNC
jsr ClearRAM ; clear RAM
jsr WaitSync ; wait for VSYNC (and PPU warmup)

NMI:
LoadSprites:
ldx #$00
LoadSpritesLoop:
lda Sprites, x
sta OAM_RAM, x
inx
cpx #$10
bne LoadSpritesLoop

lda #HIGH(background)
sta backHi
lda #LOW(background)
sta backLo

Sprites:
;vert tile attr horiz
.db $80, $01, %00000000, $80 ;sprite 0
.db $80, $02, %00110011, $88 ;sprite 1
.db $88, $03, %00110011, $80 ;sprite 2
.db $88, $05, %00000000, $88 ;sprite 3

.include "somefile.asm"
.incbin "somefile.chr"
background:
.incbin "background.chr"

;; CPU interrupts
.org $FFFA
.dw NMI ; vblank NMI
.dw RESET ; Reset
.dw 0 ; IRQ