zemu 0.4.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/zemu/config.rb +401 -391
- data/lib/zemu/debug.rb +39 -6
- data/lib/zemu/instance.rb +110 -1
- data/lib/zemu/interactive.rb +21 -1
- data/lib/zemu.rb +17 -32
- data/src/bus.c.erb +99 -0
- data/src/bus.h.erb +53 -0
- data/src/debug.h +1 -2
- data/src/main.c +1 -2
- metadata +4 -6
- data/src/io.c.erb +0 -52
- data/src/io.h.erb +0 -25
- data/src/memory.c.erb +0 -59
- data/src/memory.h.erb +0 -11
data/lib/zemu/debug.rb
CHANGED
@@ -5,22 +5,55 @@ module Zemu
|
|
5
5
|
# Loads a map file at the given path, and returns a hash of address => Symbol
|
6
6
|
# for the symbols defined within.
|
7
7
|
def self.load_map(path)
|
8
|
-
symbols =
|
8
|
+
symbols = []
|
9
9
|
|
10
10
|
File.open(path, "r") do |f|
|
11
11
|
f.each_line do |l|
|
12
12
|
s = Symbol.parse(l)
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
symbols << s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
return Symbols.new(symbols)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Contains a set of symbols.
|
22
|
+
# Allows for various lookup operations.
|
23
|
+
class Symbols
|
24
|
+
# Constructor.
|
25
|
+
def initialize(syms)
|
26
|
+
@syms = []
|
27
|
+
syms.each do |s|
|
28
|
+
@syms << s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Access all symbols with a given address.
|
33
|
+
def [](address)
|
34
|
+
at_address = []
|
35
|
+
@syms.each do |s|
|
36
|
+
if s.address == address
|
37
|
+
at_address << s
|
16
38
|
end
|
39
|
+
end
|
40
|
+
|
41
|
+
return at_address.sort_by(&:label)
|
42
|
+
end
|
17
43
|
|
18
|
-
|
19
|
-
|
44
|
+
# Find a symbol with a given name.
|
45
|
+
def find_by_name(name)
|
46
|
+
@syms.each do |s|
|
47
|
+
return s if s.label == name
|
20
48
|
end
|
49
|
+
|
50
|
+
return nil
|
21
51
|
end
|
22
52
|
|
23
|
-
|
53
|
+
# Get symbols as a hash.
|
54
|
+
def hash
|
55
|
+
return @syms
|
56
|
+
end
|
24
57
|
end
|
25
58
|
|
26
59
|
# Represents a symbol definition, of the form `label = address`.
|
data/lib/zemu/instance.rb
CHANGED
@@ -60,7 +60,15 @@ module Zemu
|
|
60
60
|
UNDEFINED = -1
|
61
61
|
end
|
62
62
|
|
63
|
+
|
64
|
+
|
63
65
|
def initialize(configuration)
|
66
|
+
@devices = configuration.devices
|
67
|
+
|
68
|
+
# Methods defined by bus devices that we make
|
69
|
+
# accessible to the user.
|
70
|
+
@device_methods = []
|
71
|
+
|
64
72
|
@clock = configuration.clock_speed
|
65
73
|
@serial_delay = configuration.serial_delay
|
66
74
|
|
@@ -69,6 +77,70 @@ module Zemu
|
|
69
77
|
@serial = []
|
70
78
|
|
71
79
|
@instance = @wrapper.zemu_init
|
80
|
+
|
81
|
+
# Declare handlers.
|
82
|
+
# Memory write handler.
|
83
|
+
@mem_write = Proc.new do |addr, value|
|
84
|
+
@devices.each do |d|
|
85
|
+
d.mem_write(addr, value)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Memory read handler.
|
90
|
+
@mem_read = Proc.new do |addr|
|
91
|
+
r = 0
|
92
|
+
@devices.each do |d|
|
93
|
+
v = d.mem_read(addr)
|
94
|
+
unless v.nil?
|
95
|
+
r = v
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
r
|
100
|
+
end
|
101
|
+
|
102
|
+
# IO write handler.
|
103
|
+
@io_write = Proc.new do |port, value|
|
104
|
+
@devices.each do |d|
|
105
|
+
d.io_write(port, value)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# IO read handler.
|
110
|
+
@io_read = Proc.new do |port|
|
111
|
+
r = 0
|
112
|
+
@devices.each do |d|
|
113
|
+
v = d.io_read(port)
|
114
|
+
unless v.nil?
|
115
|
+
r = v
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
r
|
120
|
+
end
|
121
|
+
|
122
|
+
# IO read handler.
|
123
|
+
@io_clock = Proc.new do
|
124
|
+
@devices.each do |d|
|
125
|
+
d.clock()
|
126
|
+
end
|
127
|
+
|
128
|
+
bus_state = 0
|
129
|
+
|
130
|
+
if @devices.any? { |d| d.nmi? }
|
131
|
+
bus_state |= 1
|
132
|
+
end
|
133
|
+
|
134
|
+
bus_state
|
135
|
+
end
|
136
|
+
|
137
|
+
# Attach handlers.
|
138
|
+
@wrapper.zemu_set_mem_write_handler(@mem_write)
|
139
|
+
@wrapper.zemu_set_mem_read_handler(@mem_read)
|
140
|
+
@wrapper.zemu_set_io_write_handler(@io_write)
|
141
|
+
@wrapper.zemu_set_io_read_handler(@io_read)
|
142
|
+
@wrapper.zemu_set_io_clock_handler(@io_clock)
|
143
|
+
|
72
144
|
@wrapper.zemu_power_on(@instance)
|
73
145
|
@wrapper.zemu_reset(@instance)
|
74
146
|
|
@@ -77,6 +149,18 @@ module Zemu
|
|
77
149
|
@breakpoints = {}
|
78
150
|
end
|
79
151
|
|
152
|
+
# Returns the device with the given name, or nil
|
153
|
+
# if no such device exists.
|
154
|
+
def device(name)
|
155
|
+
@devices.each do |d|
|
156
|
+
if d.name == name
|
157
|
+
return d
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
|
80
164
|
# Returns the clock speed of this instance in Hz.
|
81
165
|
def clock_speed
|
82
166
|
return @clock
|
@@ -253,6 +337,21 @@ module Zemu
|
|
253
337
|
|
254
338
|
wrapper.ffi_lib [File.join(configuration.output_directory, "#{configuration.name}.so")]
|
255
339
|
|
340
|
+
# Handler types for handling bus accesses.
|
341
|
+
wrapper.callback :mem_write_handler, [:uint32, :uint8], :void
|
342
|
+
wrapper.callback :mem_read_handler, [:uint32], :uint8
|
343
|
+
|
344
|
+
wrapper.callback :io_write_handler, [:uint8, :uint8], :void
|
345
|
+
wrapper.callback :io_read_handler, [:uint8], :uint8
|
346
|
+
wrapper.callback :io_clock_handler, [:void], :uint8
|
347
|
+
|
348
|
+
wrapper.attach_function :zemu_set_mem_write_handler, [:mem_write_handler], :void
|
349
|
+
wrapper.attach_function :zemu_set_mem_read_handler, [:mem_read_handler], :void
|
350
|
+
|
351
|
+
wrapper.attach_function :zemu_set_io_write_handler, [:io_write_handler], :void
|
352
|
+
wrapper.attach_function :zemu_set_io_read_handler, [:io_read_handler], :void
|
353
|
+
wrapper.attach_function :zemu_set_io_clock_handler, [:io_clock_handler], :void
|
354
|
+
|
256
355
|
wrapper.attach_function :zemu_init, [], :pointer
|
257
356
|
wrapper.attach_function :zemu_free, [:pointer], :void
|
258
357
|
|
@@ -271,15 +370,25 @@ module Zemu
|
|
271
370
|
wrapper.attach_function :zemu_debug_get_memory, [:uint16], :uint8
|
272
371
|
wrapper.attach_function :zemu_debug_set_memory, [:uint16, :uint8], :void
|
273
372
|
|
274
|
-
configuration.
|
373
|
+
configuration.devices.each do |device|
|
275
374
|
device.functions.each do |f|
|
276
375
|
wrapper.attach_function(f["name"].to_sym, f["args"], f["return"])
|
376
|
+
@device_methods << f["name"].to_sym
|
277
377
|
end
|
278
378
|
end
|
279
379
|
|
280
380
|
return wrapper
|
281
381
|
end
|
282
382
|
|
383
|
+
# Redirects calls to I/O FFI functions.
|
384
|
+
def method_missing(method, *args)
|
385
|
+
if @device_methods.include? method
|
386
|
+
return @wrapper.send(method)
|
387
|
+
end
|
388
|
+
|
389
|
+
super
|
390
|
+
end
|
391
|
+
|
283
392
|
private :make_wrapper
|
284
393
|
end
|
285
394
|
end
|
data/lib/zemu/interactive.rb
CHANGED
@@ -11,6 +11,7 @@ module Zemu
|
|
11
11
|
# to the emulator window.
|
12
12
|
def initialize(instance, options = {})
|
13
13
|
@print_serial = options[:print_serial]
|
14
|
+
@trace = []
|
14
15
|
|
15
16
|
@instance = instance
|
16
17
|
|
@@ -70,6 +71,9 @@ module Zemu
|
|
70
71
|
elsif cmd[0] == "map"
|
71
72
|
load_map(cmd[1])
|
72
73
|
|
74
|
+
elsif cmd[0] == "trace"
|
75
|
+
trace()
|
76
|
+
|
73
77
|
elsif cmd[0] == "help"
|
74
78
|
log "Available commands:"
|
75
79
|
log " continue [<n>] - Continue execution for <n> cycles"
|
@@ -90,6 +94,14 @@ module Zemu
|
|
90
94
|
close
|
91
95
|
end
|
92
96
|
|
97
|
+
# Print trace for the emulator instance
|
98
|
+
# (last 200 addresses visited).
|
99
|
+
def trace
|
100
|
+
@trace.each do |t|
|
101
|
+
puts "%04x" % t
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
93
105
|
# Outputs a table giving the current values of the instance's registers.
|
94
106
|
# For the 16-bit registers (BC, DE, HL, IX, IY, SP, PC), attempts to identify the symbol
|
95
107
|
# to which they point.
|
@@ -185,6 +197,9 @@ module Zemu
|
|
185
197
|
cycles_left -= cycles_done
|
186
198
|
actual_cycles += cycles_done
|
187
199
|
|
200
|
+
@trace << r16("PC")
|
201
|
+
@trace = @trace[1..] if @trace.size > 200
|
202
|
+
|
188
203
|
# Get time after execution.
|
189
204
|
ending = Time.now
|
190
205
|
|
@@ -199,6 +214,11 @@ module Zemu
|
|
199
214
|
sleep(padding) unless padding < 0
|
200
215
|
end
|
201
216
|
|
217
|
+
if (@instance.memory(0x200) != 0xf3)
|
218
|
+
log "Buffer overflow at #{r16("PC")}"
|
219
|
+
break
|
220
|
+
end
|
221
|
+
|
202
222
|
# Have we hit a breakpoint or HALT instruction?
|
203
223
|
if @instance.break?
|
204
224
|
log "Hit breakpoint at #{r16("PC")}."
|
@@ -258,7 +278,7 @@ module Zemu
|
|
258
278
|
|
259
279
|
syms = {}
|
260
280
|
begin
|
261
|
-
syms.merge! Debug.load_map(path.to_s)
|
281
|
+
syms.merge! Debug.load_map(path.to_s).hash
|
262
282
|
rescue ArgumentError => e
|
263
283
|
log "Error loading map file: #{e.message}"
|
264
284
|
syms.clear
|
data/lib/zemu.rb
CHANGED
@@ -62,10 +62,12 @@ module Zemu
|
|
62
62
|
SRC = File.join(__dir__, "..", "src")
|
63
63
|
|
64
64
|
# Build and start an emulator according to the given configuration.
|
65
|
+
# Returns the emulator instance.
|
65
66
|
#
|
66
67
|
# @param [Zemu::Config] configuration The configuration for which an emulator will be generated.
|
67
|
-
|
68
|
-
|
68
|
+
# @param user_defines Any user-defined preprocessor macros.
|
69
|
+
def Zemu::start(configuration, user_defines={})
|
70
|
+
build(configuration, user_defines)
|
69
71
|
|
70
72
|
return Instance.new(configuration)
|
71
73
|
end
|
@@ -81,11 +83,11 @@ module Zemu
|
|
81
83
|
end
|
82
84
|
|
83
85
|
# Builds a library according to the given configuration.
|
86
|
+
# Returns true if the build is a success, false (build failed) or nil (compiler not found) otherwise.
|
84
87
|
#
|
85
88
|
# @param [Zemu::Config] configuration The configuration for which an emulator will be generated.
|
86
|
-
#
|
87
|
-
|
88
|
-
def Zemu::build(configuration)
|
89
|
+
# @param user_defines Any user-defined preprocessor macros.
|
90
|
+
def Zemu::build(configuration, user_defines={})
|
89
91
|
# Create the output directory unless it already exists.
|
90
92
|
unless Dir.exist? configuration.output_directory
|
91
93
|
Dir.mkdir configuration.output_directory
|
@@ -109,13 +111,15 @@ module Zemu
|
|
109
111
|
|
110
112
|
inputs_str = inputs.map { |i| File.join(SRC, i) }.join(" ")
|
111
113
|
|
112
|
-
inputs_str += " " + File.join(autogen, "
|
114
|
+
inputs_str += " " + File.join(autogen, "bus.c")
|
113
115
|
|
114
116
|
defines = {
|
115
117
|
"CPU_Z80_STATIC" => 1,
|
116
118
|
"CPU_Z80_USE_LOCAL_HEADER" => 1
|
117
119
|
}
|
118
120
|
|
121
|
+
defines.merge! user_defines
|
122
|
+
|
119
123
|
defines_str = defines.map { |d, v| "-D#{d}=#{v}" }.join(" ")
|
120
124
|
|
121
125
|
includes = [
|
@@ -139,32 +143,13 @@ module Zemu
|
|
139
143
|
#
|
140
144
|
# @param [Zemu::Config] configuration The configuration for which an emulator will be generated.
|
141
145
|
def Zemu::generate(configuration)
|
142
|
-
|
143
|
-
generate_io(configuration)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Generates the memory.c and memory.h files for a given configuration.
|
147
|
-
def Zemu::generate_memory(configuration)
|
148
|
-
header_template = ERB.new File.read(File.join(SRC, "memory.h.erb"))
|
149
|
-
source_template = ERB.new File.read(File.join(SRC, "memory.c.erb"))
|
150
|
-
|
151
|
-
autogen = File.join(configuration.output_directory, "autogen_#{configuration.name}")
|
152
|
-
|
153
|
-
unless Dir.exist? autogen
|
154
|
-
Dir.mkdir autogen
|
155
|
-
end
|
156
|
-
|
157
|
-
File.write(File.join(autogen, "memory.h"),
|
158
|
-
header_template.result(configuration.get_binding))
|
159
|
-
|
160
|
-
File.write(File.join(autogen, "memory.c"),
|
161
|
-
source_template.result(configuration.get_binding))
|
146
|
+
generate_bus(configuration)
|
162
147
|
end
|
163
148
|
|
164
|
-
# Generates the
|
165
|
-
def Zemu::
|
166
|
-
header_template = ERB.new File.read(File.join(SRC, "
|
167
|
-
source_template = ERB.new File.read(File.join(SRC, "
|
149
|
+
# Generates the bus.c and bus.h files for a given configuration.
|
150
|
+
def Zemu::generate_bus(configuration)
|
151
|
+
header_template = ERB.new File.read(File.join(SRC, "bus.h.erb"))
|
152
|
+
source_template = ERB.new File.read(File.join(SRC, "bus.c.erb"))
|
168
153
|
|
169
154
|
autogen = File.join(configuration.output_directory, "autogen_#{configuration.name}")
|
170
155
|
|
@@ -172,10 +157,10 @@ module Zemu
|
|
172
157
|
Dir.mkdir autogen
|
173
158
|
end
|
174
159
|
|
175
|
-
File.write(File.join(autogen, "
|
160
|
+
File.write(File.join(autogen, "bus.h"),
|
176
161
|
header_template.result(configuration.get_binding))
|
177
162
|
|
178
|
-
File.write(File.join(autogen, "
|
163
|
+
File.write(File.join(autogen, "bus.c"),
|
179
164
|
source_template.result(configuration.get_binding))
|
180
165
|
end
|
181
166
|
end
|
data/src/bus.c.erb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
#include "bus.h"
|
2
|
+
|
3
|
+
mem_write_handler_t * mem_write_handler;
|
4
|
+
mem_read_handler_t * mem_read_handler;
|
5
|
+
|
6
|
+
io_write_handler_t * io_write_handler;
|
7
|
+
io_read_handler_t * io_read_handler;
|
8
|
+
io_clock_handler_t * io_clock_handler;
|
9
|
+
|
10
|
+
void zemu_set_mem_write_handler(mem_write_handler_t * h)
|
11
|
+
{
|
12
|
+
mem_write_handler = h;
|
13
|
+
}
|
14
|
+
|
15
|
+
void zemu_set_mem_read_handler(mem_read_handler_t * h)
|
16
|
+
{
|
17
|
+
mem_read_handler = h;
|
18
|
+
}
|
19
|
+
|
20
|
+
void zemu_set_io_write_handler(io_write_handler_t * h)
|
21
|
+
{
|
22
|
+
io_write_handler = h;
|
23
|
+
}
|
24
|
+
|
25
|
+
void zemu_set_io_read_handler(io_read_handler_t * h)
|
26
|
+
{
|
27
|
+
io_read_handler = h;
|
28
|
+
}
|
29
|
+
|
30
|
+
void zemu_set_io_clock_handler(io_clock_handler_t * h)
|
31
|
+
{
|
32
|
+
io_clock_handler = h;
|
33
|
+
}
|
34
|
+
|
35
|
+
zuint8 zemu_memory_read(void * context, zuint16 address)
|
36
|
+
{
|
37
|
+
zuint32 address_32 = address;
|
38
|
+
return mem_read_handler(address_32);
|
39
|
+
}
|
40
|
+
|
41
|
+
void zemu_memory_write(void * context, zuint16 address, zuint8 value)
|
42
|
+
{
|
43
|
+
zuint32 address_32 = address;
|
44
|
+
mem_write_handler(address_32, value);
|
45
|
+
}
|
46
|
+
|
47
|
+
zuint8 zemu_memory_peek(zuint16 address)
|
48
|
+
{
|
49
|
+
zuint32 address_32 = address;
|
50
|
+
return mem_read_handler(address_32);
|
51
|
+
}
|
52
|
+
|
53
|
+
void zemu_memory_poke(zuint16 address, zuint8 value)
|
54
|
+
{
|
55
|
+
zuint32 address_32 = address;
|
56
|
+
mem_write_handler(address_32, value);
|
57
|
+
}
|
58
|
+
|
59
|
+
void zemu_io_nmi(Z80 * instance)
|
60
|
+
{
|
61
|
+
z80_nmi(instance);
|
62
|
+
}
|
63
|
+
|
64
|
+
void zemu_io_int_on(Z80 * instance)
|
65
|
+
{
|
66
|
+
z80_int(instance, TRUE);
|
67
|
+
}
|
68
|
+
|
69
|
+
void zemu_io_int_off(Z80 * instance)
|
70
|
+
{
|
71
|
+
z80_int(instance, FALSE);
|
72
|
+
}
|
73
|
+
|
74
|
+
zuint8 zemu_io_in(void * context, zuint16 port)
|
75
|
+
{
|
76
|
+
/* Z80 IO ports occupy the lower half of the address bus.
|
77
|
+
* We cannot assume that the top half is valid.
|
78
|
+
*/
|
79
|
+
port &= 0x00FF;
|
80
|
+
|
81
|
+
return io_read_handler((zuint8)port);
|
82
|
+
}
|
83
|
+
|
84
|
+
void zemu_io_out(void * context, zuint16 port, zuint8 value)
|
85
|
+
{
|
86
|
+
/* Z80 IO ports occupy the lower half of the address bus.
|
87
|
+
* We cannot assume that the top half is valid.
|
88
|
+
*/
|
89
|
+
port &= 0x00FF;
|
90
|
+
|
91
|
+
io_write_handler((zuint8)port, value);
|
92
|
+
}
|
93
|
+
|
94
|
+
void zemu_io_clock(Z80 * instance)
|
95
|
+
{
|
96
|
+
zuint8 bus_state = io_clock_handler();
|
97
|
+
|
98
|
+
if (bus_state & 0x01) zemu_io_nmi(instance);
|
99
|
+
}
|
data/src/bus.h.erb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#ifndef _ZEMU_IO_H
|
2
|
+
#define _ZEMU_IO_H
|
3
|
+
|
4
|
+
#include "emulation/CPU/Z80.h"
|
5
|
+
|
6
|
+
#ifndef ZEMU_IO_SERIAL_BUFFER_SIZE
|
7
|
+
#define ZEMU_IO_SERIAL_BUFFER_SIZE 256
|
8
|
+
#endif
|
9
|
+
|
10
|
+
typedef struct {
|
11
|
+
zuint8 buffer[ZEMU_IO_SERIAL_BUFFER_SIZE];
|
12
|
+
unsigned int head;
|
13
|
+
unsigned int tail;
|
14
|
+
} SerialBuffer;
|
15
|
+
|
16
|
+
/* Type of a function writing to a memory address. */
|
17
|
+
typedef void mem_write_handler_t(zuint32, zuint8);
|
18
|
+
|
19
|
+
/* Type of a function reading from a memory address. */
|
20
|
+
typedef zuint8 mem_read_handler_t(zuint32);
|
21
|
+
|
22
|
+
/* Type of a function writing to an IO port. */
|
23
|
+
typedef void io_write_handler_t(zuint8, zuint8);
|
24
|
+
|
25
|
+
/* Type of a function reading from an IO port. */
|
26
|
+
typedef zuint8 io_read_handler_t(zuint8);
|
27
|
+
|
28
|
+
/* Type of a function to handle a clock cycle for a peripheral. */
|
29
|
+
typedef zuint8 io_clock_handler_t(void);
|
30
|
+
|
31
|
+
void zemu_set_mem_write_handler(mem_write_handler_t * h);
|
32
|
+
void zemu_set_mem_read_handler(mem_read_handler_t * h);
|
33
|
+
|
34
|
+
void zemu_set_io_write_handler(io_write_handler_t * h);
|
35
|
+
void zemu_set_io_read_handler(io_read_handler_t * h);
|
36
|
+
void zemu_set_io_clock_handler(io_clock_handler_t * h);
|
37
|
+
|
38
|
+
zuint8 zemu_memory_read(void * context, zuint16 address);
|
39
|
+
void zemu_memory_write(void * context, zuint16 address, zuint8 value);
|
40
|
+
|
41
|
+
zuint8 zemu_memory_peek(zuint16 address);
|
42
|
+
void zemu_memory_poke(zuint16 address, zuint8 value);
|
43
|
+
|
44
|
+
void zemu_io_serial_master_puts(zuint8 val);
|
45
|
+
zuint8 zemu_io_serial_master_gets(void);
|
46
|
+
zusize zemu_io_serial_buffer_size(void);
|
47
|
+
|
48
|
+
zuint8 zemu_io_in(void * context, zuint16 port);
|
49
|
+
void zemu_io_out(void * context, zuint16 port, zuint8 value);
|
50
|
+
void zemu_io_nmi(Z80 * instance);
|
51
|
+
void zemu_io_clock(Z80 * instance);
|
52
|
+
|
53
|
+
#endif
|
data/src/debug.h
CHANGED
data/src/main.c
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zemu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jay Valentine
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Zemu is a gem which allows the user to configure a Z80-based system
|
@@ -32,6 +32,8 @@ files:
|
|
32
32
|
- lib/zemu/debug.rb
|
33
33
|
- lib/zemu/instance.rb
|
34
34
|
- lib/zemu/interactive.rb
|
35
|
+
- src/bus.c.erb
|
36
|
+
- src/bus.h.erb
|
35
37
|
- src/debug.c
|
36
38
|
- src/debug.h
|
37
39
|
- src/external/Z/API/Z/ABIs/generic/allocator.h
|
@@ -310,11 +312,7 @@ files:
|
|
310
312
|
- src/external/z80/sources/Z80.c
|
311
313
|
- src/interrupt.c
|
312
314
|
- src/interrupt.h
|
313
|
-
- src/io.c.erb
|
314
|
-
- src/io.h.erb
|
315
315
|
- src/main.c
|
316
|
-
- src/memory.c.erb
|
317
|
-
- src/memory.h.erb
|
318
316
|
homepage: https://github.com/jayvalentine/zemu
|
319
317
|
licenses:
|
320
318
|
- GPL-3.0
|
data/src/io.c.erb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
#include "io.h"
|
2
|
-
|
3
|
-
<% io.each do |device| %>
|
4
|
-
<%= device.setup %>
|
5
|
-
<% end %>
|
6
|
-
|
7
|
-
void zemu_io_nmi(Z80 * instance)
|
8
|
-
{
|
9
|
-
z80_nmi(instance);
|
10
|
-
}
|
11
|
-
|
12
|
-
void zemu_io_int_on(Z80 * instance)
|
13
|
-
{
|
14
|
-
z80_int(instance, TRUE);
|
15
|
-
}
|
16
|
-
|
17
|
-
void zemu_io_int_off(Z80 * instance)
|
18
|
-
{
|
19
|
-
z80_int(instance, FALSE);
|
20
|
-
}
|
21
|
-
|
22
|
-
zuint8 zemu_io_in(void * context, zuint16 port)
|
23
|
-
{
|
24
|
-
/* Z80 IO ports occupy the lower half of the address bus.
|
25
|
-
* We cannot assume that the top half is valid.
|
26
|
-
*/
|
27
|
-
port &= 0x00FF;
|
28
|
-
|
29
|
-
<% io.each do |device| %>
|
30
|
-
<%= device.read %>
|
31
|
-
<% end %>
|
32
|
-
return 0;
|
33
|
-
}
|
34
|
-
|
35
|
-
void zemu_io_out(void * context, zuint16 port, zuint8 value)
|
36
|
-
{
|
37
|
-
/* Z80 IO ports occupy the lower half of the address bus.
|
38
|
-
* We cannot assume that the top half is valid.
|
39
|
-
*/
|
40
|
-
port &= 0x00FF;
|
41
|
-
|
42
|
-
<% io.each do |device| %>
|
43
|
-
<%= device.write %>
|
44
|
-
<% end %>
|
45
|
-
}
|
46
|
-
|
47
|
-
void zemu_io_clock(Z80 * instance)
|
48
|
-
{
|
49
|
-
<% io.each do |device| %>
|
50
|
-
<%= device.clock %>
|
51
|
-
<% end %>
|
52
|
-
}
|
data/src/io.h.erb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#ifndef _ZEMU_IO_H
|
2
|
-
#define _ZEMU_IO_H
|
3
|
-
|
4
|
-
#include "emulation/CPU/Z80.h"
|
5
|
-
|
6
|
-
#ifndef ZEMU_IO_SERIAL_BUFFER_SIZE
|
7
|
-
#define ZEMU_IO_SERIAL_BUFFER_SIZE 256
|
8
|
-
#endif
|
9
|
-
|
10
|
-
typedef struct {
|
11
|
-
zuint8 buffer[ZEMU_IO_SERIAL_BUFFER_SIZE];
|
12
|
-
unsigned int head;
|
13
|
-
unsigned int tail;
|
14
|
-
} SerialBuffer;
|
15
|
-
|
16
|
-
void zemu_io_serial_master_puts(zuint8 val);
|
17
|
-
zuint8 zemu_io_serial_master_gets(void);
|
18
|
-
zusize zemu_io_serial_buffer_size(void);
|
19
|
-
|
20
|
-
zuint8 zemu_io_in(void * context, zuint16 port);
|
21
|
-
void zemu_io_out(void * context, zuint16 port, zuint8 value);
|
22
|
-
void zemu_io_nmi(Z80 * instance);
|
23
|
-
void zemu_io_clock(Z80 * instance);
|
24
|
-
|
25
|
-
#endif
|