fixes for IME instructions and time

This commit is contained in:
Colby 2016-07-23 23:09:31 +10:00
parent c0780010a5
commit db5044effa
3 changed files with 21 additions and 16 deletions

View file

@ -65,6 +65,7 @@ module Waterfoul
@a = @b = @c = @d = @e = @f = @h = @l = @f = 0x00 @a = @b = @c = @d = @e = @f = @h = @l = @f = 0x00
@m = 0 @m = 0
@timer = Timer.new @timer = Timer.new
@ime = false
end end
# This method emulates the CPU cycle process. Each instruction is # This method emulates the CPU cycle process. Each instruction is
@ -72,13 +73,9 @@ module Waterfoul
# This processes repeats infinitly until the process is closed # This processes repeats infinitly until the process is closed
def step def step
reset_tick reset_tick
if halted? serve_interrupt if @ime
halt_step instruction_byte = fetch_instruction
else perform_instruction instruction_byte
serve_interrupt if @ime
instruction_byte = fetch_instruction
perform_instruction instruction_byte
end
@timer.tick @m @timer.tick @m
end end
@ -107,7 +104,7 @@ module Waterfoul
raise 'instruction not found' if operation.nil? raise 'instruction not found' if operation.nil?
# perform the instruction # perform the instruction
self.public_send operation self.public_send operation
@m = instruction_cycle_time instruction @m = instruction_cycle_time(instruction) * 4
end end
# fetch the next byte to be executed from memory and increment the program # fetch the next byte to be executed from memory and increment the program
@ -123,7 +120,9 @@ module Waterfoul
# get the number of cycles a instruction takes to execute. The times # get the number of cycles a instruction takes to execute. The times
# can be found in the instruction opcode table # can be found in the instruction opcode table
def instruction_cycle_time(instruction) def instruction_cycle_time(instruction)
if @branched if @prefix_cb
CB_OPCODE_TIMINGS[@prefix_cb]
elsif @branched
OPCODE_CONDITIONAL_TIMINGS[instruction] OPCODE_CONDITIONAL_TIMINGS[instruction]
else else
OPCODE_TIMINGS[instruction] OPCODE_TIMINGS[instruction]
@ -137,24 +136,30 @@ module Waterfoul
# master disable interrupts # master disable interrupts
@ime = false @ime = false
push_onto_stack @pc push_onto_stack @pc
@m = 20 if_reg = $mmu.read_byte 0xFF0F
# point to instruction which handles appropiate interrupt
case interrupt case interrupt
when Interrupt::INTERRUPT_VBLANK when Interrupt::INTERRUPT_VBLANK
@pc = 0x40 @pc = 0x40
$mmu.write_byte(0xFF0F, if_reg & 0xFE)
when Interrupt::INTERRUPT_LCDSTAT when Interrupt::INTERRUPT_LCDSTAT
@pc = 0x48 @pc = 0x48
$mmu.write_byte(0xFF0F, if_reg & 0xFD)
when Interrupt::INTERRUPT_TIMER when Interrupt::INTERRUPT_TIMER
@pc = 0x50 @pc = 0x50
$mmu.write_byte(0xFF0F, if_reg & 0xFB)
when Interrupt::INTERRUPT_SERIAL when Interrupt::INTERRUPT_SERIAL
@pc = 0x58 @pc = 0x58
$mmu.write_byte(0xFF0F, if_reg & 0xF7)
when Interrupt::INTERRUPT_JOYPAD when Interrupt::INTERRUPT_JOYPAD
@pc = 0x60 @pc = 0x60
$mmu.write_byte(0xFF0F, if_reg & 0xEF)
end end
@m = 20
end end
# reset variables that are set on every instruction # reset variables that are set on every instruction
def reset_tick def reset_tick
@prefix_cb = false
@branched = false @branched = false
@m = 0 @m = 0
end end

View file

@ -34,10 +34,10 @@ module Waterfoul
# @flags - - - - # @flags - - - -
def prefix_cb def prefix_cb
ins = $mmu.read_byte @pc ins = $mmu.read_byte @pc
@prefix_cb = ins
@pc += 1 @pc += 1
opcode = Waterfoul::CPU::CB_OPCODE[ins] opcode = Waterfoul::CPU::CB_OPCODE[ins]
#p "cb opcode: #{opcode}"
self.public_send opcode self.public_send opcode
end end

View file

@ -1,6 +1,6 @@
module Waterfoul module Waterfoul
class Timer class Timer
DIV_INC_TIME = 255 # cycles DIV_INC_TIME = 256 # cycles
def initialize def initialize
@div_cycles = 0 @div_cycles = 0
@ -9,8 +9,6 @@ module Waterfoul
end end
def tick(cycles = 0) def tick(cycles = 0)
# increment TIMA and DIV register
@tima_cycles += cycles
@div_cycles += cycles @div_cycles += cycles
# incremnt DIV register if its time to # incremnt DIV register if its time to
inc_div_register if @div_cycles >= DIV_INC_TIME inc_div_register if @div_cycles >= DIV_INC_TIME
@ -18,6 +16,8 @@ module Waterfoul
@tima.update @tima.update
# dont bother if TIMA is not running # dont bother if TIMA is not running
if @tima.running? if @tima.running?
# increment TIMA and DIV register
@tima_cycles += cycles
frequency = @tima.frequency frequency = @tima.frequency
if @tima_cycles >= frequency if @tima_cycles >= frequency
inc_tima_register inc_tima_register
@ -32,7 +32,7 @@ module Waterfoul
tima = $mmu.read_byte 0xFF06 tima = $mmu.read_byte 0xFF06
Interrupt.request_interrupt(Interrupt::INTERRUPT_TIMER) Interrupt.request_interrupt(Interrupt::INTERRUPT_TIMER)
else else
tima = (tima + 1) & 0xFF tima += 1
end end
$mmu.write_byte 0xFF05, tima, hardware_operation: true $mmu.write_byte 0xFF05, tima, hardware_operation: true