Module: Ruby6502

Defined in:
lib/ruby6502.rb,
lib/ruby6502/version.rb,
ext/ruby6502/ruby6502.c

Constant Summary collapse

INSTRUCTION_HOOKS =
[]
READ_WRITE_HOOKS =
{}
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.a_registerObject



26
27
28
29
# File 'ext/ruby6502/ruby6502.c', line 26

static VALUE a_register(VALUE self)
{
  return UINT2NUM(getA());
}

.clear_instruction_hooksObject



53
54
55
56
# File 'lib/ruby6502.rb', line 53

def clear_instruction_hooks
  unset_instruction_hooks
  INSTRUCTION_HOOKS.clear
end

.configure_rng(location) ⇒ Object



198
199
200
201
202
203
204
205
206
# File 'ext/ruby6502/ruby6502.c', line 198

static VALUE configure_rng(VALUE self, VALUE location) {
  uint16_t address;

  address = (uint16_t) NUM2UINT(location);

  if ( address > 0 && address < MEMSIZE ) {
    rng_hook_address = address;
  }
}

.deregister_read_write_hook(location, read_or_write) ⇒ Object



74
75
76
77
78
79
80
81
82
83
# File 'lib/ruby6502.rb', line 74

def deregister_read_write_hook(location, read_or_write)
  if read_or_write == :read_write
    READ_WRITE_HOOKS.delete([location, :read])
    READ_WRITE_HOOKS.delete([location, :write])
  else
    READ_WRITE_HOOKS.delete([location, read_or_write])
  end

  unset_read_write_hooks if READ_WRITE_HOOKS.empty?
end

.exec(tickCount) ⇒ Object



90
91
92
93
94
# File 'ext/ruby6502/ruby6502.c', line 90

static VALUE exec(VALUE self, VALUE tickCount)
{
  exec6502((uint32_t) NUM2ULONG(tickCount));
  return instruction_count(self);
}

.execute_instruction_hooksObject



88
89
90
# File 'lib/ruby6502.rb', line 88

def execute_instruction_hooks
  INSTRUCTION_HOOKS.each(&:call)
end

.execute_read_write_hook(location, read_or_write) ⇒ Object



92
93
94
# File 'lib/ruby6502.rb', line 92

def execute_read_write_hook(location, read_or_write)
  READ_WRITE_HOOKS[[location, read_or_write]]&.call(read_or_write)
end

.instruction_countObject



46
47
48
49
# File 'ext/ruby6502/ruby6502.c', line 46

static VALUE instruction_count(VALUE self)
{
  return ULONG2NUM(getInstructions());
}

.instruction_hooks?Boolean

Returns:

  • (Boolean)


168
169
170
171
172
173
174
175
# File 'ext/ruby6502/ruby6502.c', line 168

static VALUE get_has_instruction_hooks(VALUE self)
{
  if ( has_instruction_hooks ) {
    return Qtrue;
  } else {
    return Qfalse;
  }
}

.interrupt_requestObject



62
63
64
65
66
# File 'ext/ruby6502/ruby6502.c', line 62

static VALUE interrupt_request(VALUE self)
{
  irq6502();
  return Qtrue;
}

.load(bytearray, location: 0) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/ruby6502.rb', line 10

def load(bytearray, location: 0)
  byte_size = bytearray.size
  location = location.to_i

  if location < 0
    raise "Cannot load to a negative memory location"
  end

  if memory_size < location + byte_size
    raise "Loading #{byte_size} bytes to #{format("%04x", location)} would overflow memory"
  end

  bytearray.each do |byte|
    byte_to_load = byte.to_i & 0xff
    load_byte(location, byte_to_load)
    location += 1
  end
end

.load_byte(location, r_value) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
# File 'ext/ruby6502/ruby6502.c', line 143

static VALUE load_byte(VALUE self, VALUE location, VALUE r_value)
{
  uint16_t address;
  uint8_t value;

  address = (uint16_t) NUM2UINT(location);
  value = (uint8_t) NUM2UINT(r_value);

  write_address(address, value);

  return location;
}

.memory_sizeObject



96
97
98
99
# File 'ext/ruby6502/ruby6502.c', line 96

static VALUE memory_size(VALUE self)
{
  return UINT2NUM(MEMSIZE);
}

.non_maskable_interruptObject



68
69
70
71
72
# File 'ext/ruby6502/ruby6502.c', line 68

static VALUE non_maskable_interrupt(VALUE self)
{
  nmi6502();
  return Qtrue;
}

.program_counterObject



16
17
18
19
# File 'ext/ruby6502/ruby6502.c', line 16

static VALUE program_counter(VALUE self)
{
  return UINT2NUM(getPC());
}

.read(location:, bytes:) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/ruby6502.rb', line 29

def read(location:, bytes:)
  location = location.to_i
  bytes = bytes.to_i

  unless location >= 0 && location < memory_size
    raise "#{location} is outside memory bounds"
  end

  unless bytes >= 0
    raise "Must read a positive number of bytes"
  end

  raise "#{format("%04x", location + bytes)} is outside bounds" if location + bytes > memory_size

  bytes.times.map do |byte|
    read_byte(location + byte)
  end
end

.read_byte(location) ⇒ Object



118
119
120
121
122
123
124
125
# File 'ext/ruby6502/ruby6502.c', line 118

static VALUE read_byte(VALUE self, VALUE location)
{
  uint16_t address;

  address = (uint16_t) NUM2UINT(location);

  return UINT2NUM(read_address(address));
}

.read_write_hooks?Boolean

Returns:

  • (Boolean)


189
190
191
192
193
194
195
196
# File 'ext/ruby6502/ruby6502.c', line 189

static VALUE get_has_read_write_hooks(VALUE self)
{
  if ( has_read_write_hooks ) {
    return Qtrue;
  } else {
    return Qfalse;
  }
}

.register_instruction_hook(&hook) ⇒ Object



48
49
50
51
# File 'lib/ruby6502.rb', line 48

def register_instruction_hook(&hook)
  set_instruction_hooks unless instruction_hooks?
  INSTRUCTION_HOOKS << hook
end

.register_read_write_hook(location, read_or_write, &hook) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ruby6502.rb', line 58

def register_read_write_hook(location, read_or_write, &hook)
  read_or_write = read_or_write.to_sym
  unless [:read, :write, :read_write].include?(read_or_write)
    raise "#{read_or_write} must be one of :read, :write, :read_write"
  end

  set_read_write_hooks unless read_write_hooks?

  if read_or_write == :read_write
    READ_WRITE_HOOKS[[location, :read]] = hook
    READ_WRITE_HOOKS[[location, :write]] = hook
  else
    READ_WRITE_HOOKS[[location, read_or_write]] = hook
  end
end

.resetObject



56
57
58
59
60
# File 'ext/ruby6502/ruby6502.c', line 56

static VALUE reset(VALUE self)
{
  reset6502();
  return Qtrue;
}

.set_instruction_hooksObject



156
157
158
159
160
# File 'ext/ruby6502/ruby6502.c', line 156

static VALUE set_instruction_hooks(VALUE self)
{
  has_instruction_hooks = 1;
  return Qtrue;
}

.set_read_write_hooksObject



177
178
179
180
181
# File 'ext/ruby6502/ruby6502.c', line 177

static VALUE set_read_write_hooks(VALUE self)
{
  has_read_write_hooks = 1;
  return Qtrue;
}

.stack_pointerObject



21
22
23
24
# File 'ext/ruby6502/ruby6502.c', line 21

static VALUE stack_pointer(VALUE self)
{
  return UINT2NUM(getSP());
}

.status_flagsObject



41
42
43
44
# File 'ext/ruby6502/ruby6502.c', line 41

static VALUE status_flags(VALUE self)
{
  return UINT2NUM(getStatus());
}

.stepObject



74
75
76
77
78
# File 'ext/ruby6502/ruby6502.c', line 74

static VALUE step(VALUE self)
{
  step6502();
  return instruction_count(self);
}

.step_times(stepCount) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'ext/ruby6502/ruby6502.c', line 80

static VALUE step_times(VALUE self, VALUE stepCount)
{
  int steps = NUM2INT(stepCount);
  for(int i = 0; i < steps; ++i) {
    step6502();
  }

  return instruction_count(self);
}

.tick_countObject



51
52
53
54
# File 'ext/ruby6502/ruby6502.c', line 51

static VALUE tick_count(VALUE self)
{
  return ULL2NUM(getTicks());
}

.unset_instruction_hooksObject



162
163
164
165
166
# File 'ext/ruby6502/ruby6502.c', line 162

static VALUE unset_instruction_hooks(VALUE self)
{
  has_instruction_hooks = 0;
  return Qtrue;
}

.unset_read_write_hooksObject



183
184
185
186
187
# File 'ext/ruby6502/ruby6502.c', line 183

static VALUE unset_read_write_hooks(VALUE self)
{
  has_read_write_hooks = 0;
  return Qtrue;
}

.x_registerObject



31
32
33
34
# File 'ext/ruby6502/ruby6502.c', line 31

static VALUE x_register(VALUE self)
{
  return UINT2NUM(getX());
}

.y_registerObject



36
37
38
39
# File 'ext/ruby6502/ruby6502.c', line 36

static VALUE y_register(VALUE self)
{
  return UINT2NUM(getY());
}