From 5ee093760d1f9aa968fd28cfc362d0bd1bb4345c Mon Sep 17 00:00:00 2001 From: Colby Date: Fri, 19 Aug 2016 20:49:24 +1000 Subject: [PATCH] documentation updats --- lib/waterfoul/boot_rom.rb | 1 - lib/waterfoul/cpu.rb | 27 +++++++++++---------------- lib/waterfoul/emulator.rb | 25 +++++++------------------ lib/waterfoul/helper.rb | 1 + lib/waterfoul/interrupt.rb | 1 + lib/waterfoul/mmu.rb | 17 +++++++---------- lib/waterfoul/skip_boot.rb | 9 ++++++--- 7 files changed, 33 insertions(+), 48 deletions(-) diff --git a/lib/waterfoul/boot_rom.rb b/lib/waterfoul/boot_rom.rb index b8db863..d366222 100644 --- a/lib/waterfoul/boot_rom.rb +++ b/lib/waterfoul/boot_rom.rb @@ -51,7 +51,6 @@ module Waterfoul # Read bootstrap instruction given an index (memory location) - # @return Integer - instruction or immediate value def self.[](i) ROM[i] end diff --git a/lib/waterfoul/cpu.rb b/lib/waterfoul/cpu.rb index d1fef75..117149a 100644 --- a/lib/waterfoul/cpu.rb +++ b/lib/waterfoul/cpu.rb @@ -9,8 +9,8 @@ require 'waterfoul/instructions/shift' require 'waterfoul/instructions/prefix' module Waterfoul - # These constants represent each state in the F register and are used as a helper to - # reference the state when setting/resetting a state bit. Any combination of these + # These constants represent status bit in the F register. These are used as a + # helper when setting/resetting a state bit. Any combination of these # states can be set at any one time. # # Z_FLAG: Zero Flag @@ -18,25 +18,20 @@ module Waterfoul # H_FLAG: half carry flag # C_FLAG: Carry Flag # BIT 0-3 Always 0 and not used - # Z_FLAG = 0b1000_0000 N_FLAG = 0b0100_0000 H_FLAG = 0b0010_0000 C_FLAG = 0b0001_0000 - # number of cycles a HALT will puase program execution for - HALT_CYCLES = 6 - - ## - # The CPU emulates the Sharp LR35902 CPU that is built into the device, similar to the - # Intel 8080 and Zilog Z80 processor. Each instruction is categorized - # into a subset of instructions by the type of action performed by the instruction. + # The CPU emulates the Sharp LR35902 CPU that is built into the device, + # similar to the Intel 8080 and Zilog Z80 processor. Each instruction + # is categorized into a subset of instructions by the type of action + # performed by the instruction. # - # See lib/instuctions/ for the implementation for the CPU instruction set. + # See lib/instuctions for the implementation for the CPU instruction set. # # I recommend looking at http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html for an # easy to understand chart for each instruction. - # class CPU include Helper include Instructions::Opcode @@ -51,7 +46,7 @@ module Waterfoul # 8 bit registers attr_reader :a, :b, :c, :d, :e, :f, :h, :l, :f - # 8 CPU clock + # CPU cycle count attr_reader :m # 16 bit registers attr_reader :sp, :pc @@ -89,10 +84,10 @@ module Waterfoul end def halted? - @halt == true + @halt end - # Execute the instruction and + # Execute the instruction and def perform_instruction(instruction) operation = OPCODE[instruction] raise 'instruction not found' if operation.nil? @@ -103,7 +98,7 @@ module Waterfoul # fetch the next byte to be executed from memory and increment the program # counter (except under particular circumstances, see interrupts) - def fetch_instruction(increment_pc = false) + def fetch_instruction(no_increment_pc = false) instruction_byte = $mmu.read_byte @pc @pc = (@pc + 1) & 0xFFFF unless increment_pc instruction_byte diff --git a/lib/waterfoul/emulator.rb b/lib/waterfoul/emulator.rb index 88bab09..fc65104 100644 --- a/lib/waterfoul/emulator.rb +++ b/lib/waterfoul/emulator.rb @@ -1,22 +1,18 @@ -require 'sdl2' - module Waterfoul + # The Emulator is the abstraction of the emulator as a whole, it initializes + # each component and performs the tick. class Emulator def initialize(rom_filename, options = {}) - SDL2.init SDL2::INIT_EVERYTHING - # read the rom into host memory - rom = read_program(rom_filename).bytes - # initialize emulated CPU, GPU & Sound components + # read the given file as binary and break it down into an array of bytes + rom = File.binread(rom_filename).bytes + # initialize emulated CPU, GPU & Scren components cartridge = Cartridge.new rom - # initialize emulated memory management unit $mmu = MMU.new - $mmu.cartridge = cartridge - cpu = CPU.new - @cpu = options.has_key?('skip_boot') ? SkipBoot.set_state(cpu) : cpu + @cpu = CPU.new + @cpu = SkipBoot.set_state(@cpu) if options.has_key?('skip_boot') @gpu = GPU.new # @input = Input.new @screen = Screen.new - # @sound = Sound.new end def run @@ -25,14 +21,7 @@ module Waterfoul @gpu.step @cpu.m @screen.render @gpu.framebuffer if @gpu.vblank? # @input.step @cpu.m - # @sound.step end end - - private - - def read_program(rom) - File.binread rom - end end end diff --git a/lib/waterfoul/helper.rb b/lib/waterfoul/helper.rb index a7a666b..eae555f 100644 --- a/lib/waterfoul/helper.rb +++ b/lib/waterfoul/helper.rb @@ -1,5 +1,6 @@ module Waterfoul module Helper + def pop_from_stack(word = true) if word lower = $mmu.read_byte @sp diff --git a/lib/waterfoul/interrupt.rb b/lib/waterfoul/interrupt.rb index 37abe56..520dc16 100644 --- a/lib/waterfoul/interrupt.rb +++ b/lib/waterfoul/interrupt.rb @@ -12,6 +12,7 @@ module Waterfoul INTERRUPT_SERIAL = 0x8 INTERRUPT_JOYPAD = 0x10 + # def self.request_interrupt(interrupt) if_reg = $mmu.read_byte IF_REG_MEM_LOC $mmu.write_byte IF_REG_MEM_LOC, (if_reg | interrupt) diff --git a/lib/waterfoul/mmu.rb b/lib/waterfoul/mmu.rb index 7cb20e8..11eb0e5 100644 --- a/lib/waterfoul/mmu.rb +++ b/lib/waterfoul/mmu.rb @@ -7,12 +7,11 @@ module Waterfoul # does not implement any IO instructions. class MMU MEMORY_SIZE = 65536 # bytes - # location in memory that when written to will unmap the boot rom from - # memory + # unmap boot rom register address UNMAP_BOOT_ROM_MEM_LOC = 0xFF50 # location in memory where the boot rom ends BOOT_ROM_END_MEM_LOC = 0xFF - # location in memory where DMA transfer is init + # DMA register function address DMA_TRANSFER_MEM_LOC = 0xFF46 # DIV register memory location DIV_MEM_LOC = 0xFF04 @@ -23,19 +22,19 @@ module Waterfoul # Set the initial state the memory management unit when program starts def initialize @cartridge = [] - # flag to indicate if the boot rom is mapped to memory + # map the boot rom by default @map_boot_rom = true # storage for usable memory (zero filled) @memory = Array.new MEMORY_SIZE, 0 end # Read 1 byte from memory given address - # @param i Integer location in memory to read value def [](i) raise MemoryOutOfBounds if i > MEMORY_SIZE || i < 0 case i when 0x0000...0x8000 # ROM Bank 0 + n + # if the boot rom is enabled and the address is < 0x100 if @map_boot_rom && i <= BOOT_ROM_END_MEM_LOC BootROM[i] else @@ -54,14 +53,12 @@ module Waterfoul end end - ## - # Storage 1 byte into memory given address - # @param i Integer location in memory to storage value - # @param v Integer value to be written into memory + # Write 1 byte into memory def []=(i, v, options = {}) # raise exception if an attempt is made to read memory that is out of bounds raise MemoryOutOfBounds if i > MEMORY_SIZE || i < 0 - + # ignore memory rules if emulated hardware components need to write to + # memory unless options[:hardware_operation] case i when UNMAP_BOOT_ROM_MEM_LOC # unmap the boot rom when 0xFF50 is wrtiten to in memory diff --git a/lib/waterfoul/skip_boot.rb b/lib/waterfoul/skip_boot.rb index dd69e62..9714ae9 100644 --- a/lib/waterfoul/skip_boot.rb +++ b/lib/waterfoul/skip_boot.rb @@ -1,7 +1,10 @@ module Waterfoul - # Set the state of the emulator after it has finished running the bootloader and ready to execute - # the game program. This lets us run the game program without needing to execute the boot rom every time - # the emulator is started. + # Set the state of the emulator as defined to the same state as it typically + # is after it has finished running the bootloader and ready to execute the + # game program. + + # This lets us run the game without needing to execute the boot rom + # every time the emulator is started. class SkipBoot def self.set_state(cpu) # CPU registers