diff --git a/lib/rouge/demos/nesasm b/lib/rouge/demos/nesasm new file mode 100644 index 0000000000..91a0f972f3 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/lib/rouge/lexers/nesasm.rb b/lib/rouge/lexers/nesasm.rb new file mode 100644 index 0000000000..a296414e04 --- /dev/null +++ b/lib/rouge/lexers/nesasm.rb @@ -0,0 +1,78 @@ +# -*- 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 FUNC + ) + end + + state :root do + rule %r/\s+/m, Text + rule %r(;.*), Comment::Single + + rule %r/[\(\)\,\.\[\]]/, Punctuation + rule %r/\#?\%[0-1]+/, Num::Bin # #%00110011 %00110011 + rule %r/\#?\$\h+/, Num::Hex # $1f #$1f + rule %r/\#?\d+/, Num # 10 #10 + rule %r([~&*+=\|?:<>/-]), Operator + + rule %r/\#?\w+:?/i do |m| + 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 + + rule %r/'\w'/, Str::Char # 'A' for example + + rule %r/\\\??[\d@#]/, Name::Builtin # builtin parameters for use inside macros and functions: \1-\9 , \?1-\?9 , \# , \@ + end + + state :string do + rule %r/"/, Str, :pop! + rule %r/\\"?/, Str::Escape + rule %r/[^"\\]+/m, Str + end + end + end +end diff --git a/spec/lexers/nesasm_spec.rb b/spec/lexers/nesasm_spec.rb new file mode 100644 index 0000000000..7b37f931e6 --- /dev/null +++ b/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 diff --git a/spec/visual/samples/nesasm b/spec/visual/samples/nesasm new file mode 100644 index 0000000000..6615b3c6a2 --- /dev/null +++ b/spec/visual/samples/nesasm @@ -0,0 +1,69 @@ + .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) + +SCR_ADDR .func (\1) + ((\2) << 5) + +abs .macro + lda \1 + bpl .x\@ + eor #$FF + inc A + sta \1 + + lda \# + sta numberOfParams + + lda \?4 + sta typeOfParam + + .x\@: + .endm + +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 \ No newline at end of file