diff --git a/examples/demo.asm b/examples/demo.asm index a86ea3b..e5fb220 100644 --- a/examples/demo.asm +++ b/examples/demo.asm @@ -13,10 +13,18 @@ ; Here is a good spot to associate zero page memory addresses ; with quick access variables in the program. .segment prog 0 -.org $0200 -sprite: +;;;; +; We can use scope to declare a C like struct at $0200 +.org $0200 +.scope sprite + .space y 1 + .space pattern 1 + .space color 1 + .space x 1 +. + ;;;; ; Setup the interrupt vectors .org $FFFA @@ -135,10 +143,10 @@ sprite: ; initialize Sprite 0 lda #$70 - sta $0200 ; sprite Y coordinate + sta sprite.y ; Store sprite y coordinate ;sta $0200 ; sprite Y coordinate lda #$01 - sta $0201 ; sprite + 1 Pattern number - sta $0203 ; sprite + 3 X coordinate, sprite + 2, color, stays 0. + sta sprite.pattern ; sta $0201 ; sprite + 1 Pattern number + sta sprite.x ;sta $0203 ; sprite + 3 X coordinate, sprite + 2, color, stays 0. ; Set initial value of dx lda #$01 @@ -215,7 +223,7 @@ sprite: update_sprite: lda #>sprite sta $4014 ; Jam page $200-$2FF into SPR-RAM - lda $0203 ; sprite+3 Is this right??? + lda sprite.x beq hit_left cmp #$F7 bne edge_done @@ -233,7 +241,7 @@ hit_left: edge_done: ; update X and store it. clc adc $00 ; dx - sta $0203 ; sprite+3 Is this right? + sta sprite.x rts react_to_input: @@ -259,21 +267,21 @@ react_to_input: lda $4016 ; Up and #$01 beq not_up - ldx sprite ; Load Y value + ldx sprite.y ; Load Y value cpx #$07 - beq not_up ; No going past the top of the screen + beq not_up ; No going past the top of the screen dex - stx sprite + stx sprite.y not_up: lda $4016 ; Down and #$01 beq not_dn - ldx sprite + ldx sprite.y cpx #$DF ; No going past the bottom of the screen. beq not_dn inx - stx sprite + stx sprite.y not_dn: rts ; Ignore left and right, we don't use 'em diff --git a/lib/directives/space.rb b/lib/directives/space.rb new file mode 100644 index 0000000..5d9a929 --- /dev/null +++ b/lib/directives/space.rb @@ -0,0 +1,46 @@ +require_relative '../instruction_base' + +module Assembler6502 + + + #### + ## This directive gives a symbolic name for memory and creates space for a variable in RAM + class Space < InstructionBase + + #### + ## Try to parse a .space directive + def self.parse(line) + match_data = line.match(/^.space\s+([a-zA-Z]?[a-zA-Z0-9_]+?)\s+([0-9]+)$/) + return nil if match_data.nil? + _, name, size = match_data.to_a + + Space.new(name, size.to_i) + end + + + #### + ## Initialize some memory space with a name + def initialize(name, size) + @name = name + @size = size + end + + + #### + ## .space creates a symbol at the current PC, and then advances PC by size + def exec(assembler) + program_counter = assembler.program_counter + assembler.symbol_table.define_symbol(@name, program_counter) + assembler.program_counter += @size + end + + + #### + ## Display + def to_s + ".space #{@name} #{@size}" + end + + end + +end diff --git a/lib/parser.rb b/lib/parser.rb index 6e1bb78..304f3e0 100644 --- a/lib/parser.rb +++ b/lib/parser.rb @@ -12,6 +12,7 @@ module Assembler6502 require_relative 'directives/label' require_relative 'directives/enter_scope' require_relative 'directives/exit_scope' + require_relative 'directives/space' #### @@ -24,7 +25,7 @@ module Assembler6502 class CannotParse < StandardError; end - Directives = [INESHeader, Org, Segment, IncBin, DW, Bytes, ASCII, EnterScope, ExitScope] + Directives = [INESHeader, Org, Segment, IncBin, DW, Bytes, ASCII, EnterScope, ExitScope, Space] #### ## Parses a line of program source into an object