From 404934479fb1fe897a61b5d6d3571a5ef95ded6e Mon Sep 17 00:00:00 2001
From: Safiire <safiire@gmail.com>
Date: Sun, 22 Feb 2015 05:59:03 -0800
Subject: [PATCH] Intermediate commit

---
 data/opcodes.yaml |   2 +-
 lib/assembler.rb  |  73 ++++++++++++++++++++++++++++++++++++-----
 lib/directive.rb  |  15 +++++++--
 nsf_player.asm    |  82 ++++++++++++++++++++++++++++++++++++++++++++++
 some_beeps.nsf    | Bin 0 -> 5931 bytes
 whatever.inc      |   2 ++
 6 files changed, 162 insertions(+), 12 deletions(-)
 create mode 100644 nsf_player.asm
 create mode 100644 some_beeps.nsf
 create mode 100644 whatever.inc

diff --git a/data/opcodes.yaml b/data/opcodes.yaml
index 43e14aa..ecbb676 100644
--- a/data/opcodes.yaml
+++ b/data/opcodes.yaml
@@ -280,7 +280,7 @@
     :boundry_add: false
 
 :cpy:
-  :description: "ComPare X register"
+  :description: "ComPare Y register"
   :flags: 
     - :s
     - :c
diff --git a/lib/assembler.rb b/lib/assembler.rb
index 3475179..bb58969 100644
--- a/lib/assembler.rb
+++ b/lib/assembler.rb
@@ -5,6 +5,9 @@ module Assembler6502
   ##  Let's simulate the entire 0xFFFF addressable memory space
   ##  In the NES, and create reading and writing methods for it.
   class MemorySpace
+    INESHeaderSize = 0x10
+    ProgROMSize = 0x4000
+    CharROMSize = 0x2000
 
     ####
     ##  Create a completely zeroed memory space
@@ -84,7 +87,6 @@ module Assembler6502
           fail(SyntaxError, "Already got ines header") unless @ines_header.nil?
           @ines_header = parsed_line
           puts "\tGot iNES Header"
-          #memory.write(0x0, parsed_line.emit_bytes)
 
         when Org
           address = parsed_line.address
@@ -99,22 +101,22 @@ module Assembler6502
             puts "\tSaving instruction with unresolved symbols #{parsed_line}, for second pass"
             unresolved_instructions << parsed_line
           else
-            puts "\tWriting instruction #{parsed_line} to memory"
+            puts "\tWriting instruction #{parsed_line}"
             memory.write(parsed_line.address, parsed_line.emit_bytes)
           end
           address += parsed_line.length
-          puts "\tAdvanced address to %X" % address
 
         when IncBin
-          fail("\tI Don't support .incbin yet")
-
+          puts "\t Including binary file #{parsed_line.filepath}"
+          memory.write(parsed_line.address, parsed_line.emit_bytes)
+          address += parsed_line.size
 
         when DW
           if parsed_line.unresolved_symbols?
-            puts "\tSaving .dw directive with unresolved symbols #{parsed_line}, for second pass"
+            puts "\tSaving #{parsed_line} directive with unresolved symbols, for second pass"
             unresolved_instructions << parsed_line
           else
-            puts "\tWriting .dw #{parsed_line.inspect} to memory"
+            puts "\tWriting #{parsed_line} to memory"
             memory.write(address, parsed_line.emit_bytes)
           end
           address += 2
@@ -136,11 +138,12 @@ module Assembler6502
         end
       end
 
-      print "Second pass: Resolving Symbols..."
+      puts "Second pass: Resolving Symbols..."
       unresolved_instructions.each do |instruction|
         if instruction.unresolved_symbols?
           instruction.resolve_symbols(labels)
         end
+        puts "\tResolved #{instruction}"
         memory.write(instruction.address, instruction.emit_bytes)
       end
       puts 'Done'
@@ -155,7 +158,7 @@ module Assembler6502
     ##  I am guessing the ROM size should be 1 bank of 16KB cartridge ROM
     ##  plus the 16 byte iNES header.  If the ROM is written into memory 
     ##  beginning at 0xC000, this should reach right up to the interrupt vectors
-    def assemble
+    def assemble_old
       virtual_memory = assemble_in_virtual_memory
 
       ##  First we need to be sure we have an iNES header
@@ -190,6 +193,58 @@ module Assembler6502
       #nes_rom.emit_bytes
     end
 
+
+    ####
+    ##  Another try at using the header to decide which segments
+    ##  go into the final ROM image, and which order.
+    def assemble
+      virtual_memory = assemble_in_virtual_memory
+
+      ##  First we need to be sure we have an iNES header
+      fail(INESHeaderNotFound) if @ines_header.nil?
+
+      ##  Now, we should decide how big the ROM image will be.
+      ##  And reserve memory build the image in
+      nes_rom_size  = MemorySpace::INESHeaderSize
+      nes_rom_size += @ines_header.prog * MemorySpace::ProgROMSize
+      nes_rom_size += @ines_header.char * MemorySpace::CharROMSize
+      nes_rom = MemorySpace.new(nes_rom_size)
+      puts "ROM will be #{nes_rom_size} bytes"
+
+      ##  Write the ines header to the ROM
+      nes_rom.write(0x0, @ines_header.emit_bytes)
+      puts "Wrote 16 byte ines header"
+
+      ##  If prog rom is >= 1 write the 16kb chunk from 0x8000
+      if @ines_header.prog >= 1
+        nes_rom.write(0x10, virtual_memory.read(0x8000, MemorySpace::ProgROMSize))
+        puts "Wrote 16KB byte prog rom 1"
+      end
+
+      ##  If prog rom is == 2 write the 16kb chunk from 0xC000
+      if @ines_header.prog == 2
+        nes_rom.write(0x10 + 0x4000, virtual_memory.read(0xC000, MemorySpace::ProgROMSize))
+        puts "Wrote 16KB byte prog rom 2"
+      end
+      fail("Can only have 2 prog rom slots") if @ines_header.prog > 2
+
+      ##  If char rom is >= 1 write the 8kb chunk from 0x0000
+      if @ines_header.char >= 1
+        char_start = 0x10 + (@ines_header.prog * MemorySpace::ProgROMSize)
+        nes_rom.write(char_start, virtual_memory.read(0x0000, MemorySpace::CharROMSize))
+        puts "Wrote 8KB byte char rom 1"
+      end
+
+      ##  If char rom is == 2 write the 8kb chunk from 0x2000
+      if @ines_header.char >= 1
+        char_start = 0x10 + (@ines_header.prog * MemorySpace::ProgROMSize) + MemorySpace::CharROMSize
+        nes_rom.write(char_start, virtual_memory.read(0x2000, MemorySpace::CharROMSize))
+        puts "Wrote 8KB byte char rom 2"
+      end
+
+      nes_rom.emit_bytes
+    end
+
   end
 
 end
diff --git a/lib/directive.rb b/lib/directive.rb
index 94c15e9..822d8e1 100644
--- a/lib/directive.rb
+++ b/lib/directive.rb
@@ -49,12 +49,15 @@ module Assembler6502
   ####
   ##  This is to include a binary file
   class IncBin
+    attr_reader :address, :filepath
 
     class FileNotFound < StandardError; end
 
     ####
     ##  Initialize with a file path
-    def initialize(filepath)
+    def initialize(filepath, address)
+      @filepath = filepath
+      @address = address
       unless File.exists?(filepath)
         fail(FileNotFound, ".incbin can't find #{filepath}")
       end
@@ -97,6 +100,14 @@ module Assembler6502
       end
     end
 
+    def to_s
+      if @value.kind_of?(Symbol)
+        sprintf("$%.4X | .dw #{@value}", @address)
+      else
+        sprintf("$%.4X | .dw $%.4X", @address, @value)
+      end
+    end
+
     def emit_bytes
       fail('Need to resolve symbol in .dw directive') if unresolved_symbols?
       [@value & 0xFFFF].pack('S').bytes
@@ -155,7 +166,7 @@ module Assembler6502
         Org.new($1.to_i(16))
 
       when /^\.incbin "([^"]+)"$/
-        IncBin.new($1)
+        IncBin.new($1, address)
 
       when /^\.dw\s+\$([0-9A-F]{1,4})$/
         DW.new($1.to_i(16), address)
diff --git a/nsf_player.asm b/nsf_player.asm
new file mode 100644
index 0000000..92b0ae1
--- /dev/null
+++ b/nsf_player.asm
@@ -0,0 +1,82 @@
+;  Create an iNES header
+.ines {"prog": 2, "char": 0, "mapper": 0, "mirror": 1}
+
+;  The supermario.nsf file is 17084 bytes, this includes a 0x80 byte header.
+;  It is supposed to be loaded into memory 0x8000, but we don't want that 
+;  header, so let's include the nsf to 0x8000 - 0x80 so it lines up properly
+
+.org $7F80
+.incbin "super_mario.nsf"
+
+;  Had to start this prog segment a bit later because the mario nsf is > 16KB
+.org $C300
+start:
+  CLD
+  SEI
+  LDA #$00
+  STA $2000
+
+;  Wait for 2 vblanks
+wait_vb1:
+  LDA $2002
+  BPL wait_vb1
+
+wait_vb2:
+  LDA $2002
+  BPL wait_vb2
+
+;  Clear out the sound registers
+  LDA #$00
+  LDX #$00
+clear_sound_registers:
+  STA $4000, X
+  INX
+  CPX #$0F
+  BNE clear_sound_registers
+
+  LDA #$10
+  STA $4010
+  LDA #$00
+  STA $4011
+  STA $4012
+  STA $4013
+
+;  Enable sound channels (except DMC)
+  LDA #$0F
+  STA $4015
+
+;  Reset frame counter and clock divider
+  LDA #$C0
+  STA $4017
+
+;  Set song and NTSC
+  LDA #$00          ;  Song 0
+  LDX #$00          ;  NTSC
+  JSR $8000
+
+;  Enable Vblank NMI
+  LDA #$80
+  STA $2000
+
+forever:
+  JMP forever
+
+nmi:
+  LDA $2002
+  LDA #$00
+  STA $2000
+  LDA $80
+  STA $2000
+  JSR $8000
+  RTI
+
+irq:
+  RTI
+
+.ascii "The end of prog2"
+
+.org $FFFA
+  .dw nmi
+  .dw start
+  .dw irq
+
diff --git a/some_beeps.nsf b/some_beeps.nsf
new file mode 100644
index 0000000000000000000000000000000000000000..eb1ada8721c2efbdf9cc374bff2a31cfded068a8
GIT binary patch
literal 5931
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
M{owEVw%ud?A6irrUjP6A

literal 0
HcmV?d00001

diff --git a/whatever.inc b/whatever.inc
new file mode 100644
index 0000000..856242f
--- /dev/null
+++ b/whatever.inc
@@ -0,0 +1,2 @@
+	
+
ޭޭޭޭޭޭޭޭ
\ No newline at end of file