mirror of
https://github.com/safiire/n65.git
synced 2024-12-13 06:29:16 +00:00
Intermediate commit
This commit is contained in:
parent
b94208489b
commit
404934479f
@ -280,7 +280,7 @@
|
|||||||
:boundry_add: false
|
:boundry_add: false
|
||||||
|
|
||||||
:cpy:
|
:cpy:
|
||||||
:description: "ComPare X register"
|
:description: "ComPare Y register"
|
||||||
:flags:
|
:flags:
|
||||||
- :s
|
- :s
|
||||||
- :c
|
- :c
|
||||||
|
@ -5,6 +5,9 @@ module Assembler6502
|
|||||||
## Let's simulate the entire 0xFFFF addressable memory space
|
## Let's simulate the entire 0xFFFF addressable memory space
|
||||||
## In the NES, and create reading and writing methods for it.
|
## In the NES, and create reading and writing methods for it.
|
||||||
class MemorySpace
|
class MemorySpace
|
||||||
|
INESHeaderSize = 0x10
|
||||||
|
ProgROMSize = 0x4000
|
||||||
|
CharROMSize = 0x2000
|
||||||
|
|
||||||
####
|
####
|
||||||
## Create a completely zeroed memory space
|
## Create a completely zeroed memory space
|
||||||
@ -84,7 +87,6 @@ module Assembler6502
|
|||||||
fail(SyntaxError, "Already got ines header") unless @ines_header.nil?
|
fail(SyntaxError, "Already got ines header") unless @ines_header.nil?
|
||||||
@ines_header = parsed_line
|
@ines_header = parsed_line
|
||||||
puts "\tGot iNES Header"
|
puts "\tGot iNES Header"
|
||||||
#memory.write(0x0, parsed_line.emit_bytes)
|
|
||||||
|
|
||||||
when Org
|
when Org
|
||||||
address = parsed_line.address
|
address = parsed_line.address
|
||||||
@ -99,22 +101,22 @@ module Assembler6502
|
|||||||
puts "\tSaving instruction with unresolved symbols #{parsed_line}, for second pass"
|
puts "\tSaving instruction with unresolved symbols #{parsed_line}, for second pass"
|
||||||
unresolved_instructions << parsed_line
|
unresolved_instructions << parsed_line
|
||||||
else
|
else
|
||||||
puts "\tWriting instruction #{parsed_line} to memory"
|
puts "\tWriting instruction #{parsed_line}"
|
||||||
memory.write(parsed_line.address, parsed_line.emit_bytes)
|
memory.write(parsed_line.address, parsed_line.emit_bytes)
|
||||||
end
|
end
|
||||||
address += parsed_line.length
|
address += parsed_line.length
|
||||||
puts "\tAdvanced address to %X" % address
|
|
||||||
|
|
||||||
when IncBin
|
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
|
when DW
|
||||||
if parsed_line.unresolved_symbols?
|
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
|
unresolved_instructions << parsed_line
|
||||||
else
|
else
|
||||||
puts "\tWriting .dw #{parsed_line.inspect} to memory"
|
puts "\tWriting #{parsed_line} to memory"
|
||||||
memory.write(address, parsed_line.emit_bytes)
|
memory.write(address, parsed_line.emit_bytes)
|
||||||
end
|
end
|
||||||
address += 2
|
address += 2
|
||||||
@ -136,11 +138,12 @@ module Assembler6502
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print "Second pass: Resolving Symbols..."
|
puts "Second pass: Resolving Symbols..."
|
||||||
unresolved_instructions.each do |instruction|
|
unresolved_instructions.each do |instruction|
|
||||||
if instruction.unresolved_symbols?
|
if instruction.unresolved_symbols?
|
||||||
instruction.resolve_symbols(labels)
|
instruction.resolve_symbols(labels)
|
||||||
end
|
end
|
||||||
|
puts "\tResolved #{instruction}"
|
||||||
memory.write(instruction.address, instruction.emit_bytes)
|
memory.write(instruction.address, instruction.emit_bytes)
|
||||||
end
|
end
|
||||||
puts 'Done'
|
puts 'Done'
|
||||||
@ -155,7 +158,7 @@ module Assembler6502
|
|||||||
## I am guessing the ROM size should be 1 bank of 16KB cartridge ROM
|
## 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
|
## 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
|
## beginning at 0xC000, this should reach right up to the interrupt vectors
|
||||||
def assemble
|
def assemble_old
|
||||||
virtual_memory = assemble_in_virtual_memory
|
virtual_memory = assemble_in_virtual_memory
|
||||||
|
|
||||||
## First we need to be sure we have an iNES header
|
## First we need to be sure we have an iNES header
|
||||||
@ -190,6 +193,58 @@ module Assembler6502
|
|||||||
#nes_rom.emit_bytes
|
#nes_rom.emit_bytes
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -49,12 +49,15 @@ module Assembler6502
|
|||||||
####
|
####
|
||||||
## This is to include a binary file
|
## This is to include a binary file
|
||||||
class IncBin
|
class IncBin
|
||||||
|
attr_reader :address, :filepath
|
||||||
|
|
||||||
class FileNotFound < StandardError; end
|
class FileNotFound < StandardError; end
|
||||||
|
|
||||||
####
|
####
|
||||||
## Initialize with a file path
|
## Initialize with a file path
|
||||||
def initialize(filepath)
|
def initialize(filepath, address)
|
||||||
|
@filepath = filepath
|
||||||
|
@address = address
|
||||||
unless File.exists?(filepath)
|
unless File.exists?(filepath)
|
||||||
fail(FileNotFound, ".incbin can't find #{filepath}")
|
fail(FileNotFound, ".incbin can't find #{filepath}")
|
||||||
end
|
end
|
||||||
@ -97,6 +100,14 @@ module Assembler6502
|
|||||||
end
|
end
|
||||||
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
|
def emit_bytes
|
||||||
fail('Need to resolve symbol in .dw directive') if unresolved_symbols?
|
fail('Need to resolve symbol in .dw directive') if unresolved_symbols?
|
||||||
[@value & 0xFFFF].pack('S').bytes
|
[@value & 0xFFFF].pack('S').bytes
|
||||||
@ -155,7 +166,7 @@ module Assembler6502
|
|||||||
Org.new($1.to_i(16))
|
Org.new($1.to_i(16))
|
||||||
|
|
||||||
when /^\.incbin "([^"]+)"$/
|
when /^\.incbin "([^"]+)"$/
|
||||||
IncBin.new($1)
|
IncBin.new($1, address)
|
||||||
|
|
||||||
when /^\.dw\s+\$([0-9A-F]{1,4})$/
|
when /^\.dw\s+\$([0-9A-F]{1,4})$/
|
||||||
DW.new($1.to_i(16), address)
|
DW.new($1.to_i(16), address)
|
||||||
|
82
nsf_player.asm
Normal file
82
nsf_player.asm
Normal file
@ -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
|
||||||
|
|
BIN
some_beeps.nsf
Normal file
BIN
some_beeps.nsf
Normal file
Binary file not shown.
2
whatever.inc
Normal file
2
whatever.inc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
ޭޭޭޭޭޭޭޭ
|
Loading…
Reference in New Issue
Block a user