zemu 0.2.1 → 0.2.2
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 +182 -2
- data/lib/zemu/instance.rb +5 -3
- data/src/io.c.erb +3 -100
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79900374a7a271fbfc1333290b4078e8e587ebbec09034c9cde520623459fcd4
|
4
|
+
data.tar.gz: 6282f2f1d04cf8188d84a058100d7db55d9305c3c577104455ead68195d17adb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30dcdd1f3b79b767816a23a28c34107fb91ea48a8bbff445fa90228d4c2fe83276ba4f5ffb727f881e1864edeb40cbbefe1f637cb2e07a2793c0bbbab3ecf7fb
|
7
|
+
data.tar.gz: cf6f4519a152b2f1372c581222a35bcd33a32934607bdeae878330216551a26f712a7837ddf5a9935389c4c6a1b2aeba600c2e0c178fc083bb5dce616542cf19
|
data/lib/zemu/config.rb
CHANGED
@@ -169,6 +169,53 @@ module Zemu
|
|
169
169
|
# Input/Output Port object
|
170
170
|
#
|
171
171
|
# Represents an input/output device assigned to one or more ports.
|
172
|
+
#
|
173
|
+
# This is an abstract class and cannot be instantiated directly.
|
174
|
+
# The when_setup, when_read, and when_write methods can be used to define
|
175
|
+
# the behaviour of a subclass.
|
176
|
+
#
|
177
|
+
# @example
|
178
|
+
# class MyIODevice < IOPort
|
179
|
+
# # Extend the parameters of the object so we can define a port.
|
180
|
+
# def params
|
181
|
+
# super + "port"
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# def initialize
|
185
|
+
# super
|
186
|
+
#
|
187
|
+
# # Define the setup for the IO device.
|
188
|
+
# # This is some global C code that ends up in "io.c".
|
189
|
+
# # Parameters can be used here, as the block is instance-evaluated.
|
190
|
+
# when_setup do
|
191
|
+
# %Q(zuint8 #{name}_value = 42;)
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
# # Define the logic when reading from an IO port.
|
195
|
+
# # The C variable "port" takes the value of the 8-bit port
|
196
|
+
# # address being read from, and should be used to identify
|
197
|
+
# # if this IO device is the one being used.
|
198
|
+
# when_read do
|
199
|
+
# %Q(if (port == #{port}) return #{name}_value;)
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# # Define the logic when writing to the IO port.
|
203
|
+
# # Similar to #when_read, but we have access to an extra
|
204
|
+
# # C variable, "value". This is the value being written
|
205
|
+
# # to the IO port.
|
206
|
+
# when_write do
|
207
|
+
# %Q(if (port == #{port}) #{name}_value = value;)
|
208
|
+
# end
|
209
|
+
# end
|
210
|
+
# end
|
211
|
+
#
|
212
|
+
# # The subclass can now be declared as below:
|
213
|
+
# device = MyIODevice.new do
|
214
|
+
# name "myDevice"
|
215
|
+
# port 11
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
#
|
172
219
|
class IOPort < ConfigObject
|
173
220
|
attr_reader :io_type
|
174
221
|
|
@@ -185,6 +232,67 @@ module Zemu
|
|
185
232
|
super
|
186
233
|
end
|
187
234
|
|
235
|
+
# Defines the setup behaviour of this IO device.
|
236
|
+
#
|
237
|
+
# Expects a block, the return value of which is a string
|
238
|
+
# containing all data and function declarations required by this IO device.
|
239
|
+
#
|
240
|
+
# The block will be instance-evaluated at build-time, so it is possible to use
|
241
|
+
# instance variables of the IO device.
|
242
|
+
def when_setup(&block)
|
243
|
+
@setup_block = block
|
244
|
+
end
|
245
|
+
|
246
|
+
# Defines the read behaviour of this IO device.
|
247
|
+
#
|
248
|
+
# Expects a block, the return value of which is a string
|
249
|
+
# containing the behaviour of this IO device when a value is read from the IO bus.
|
250
|
+
# Care must be taken to ensure that this functionality does not conflict with that of
|
251
|
+
# any other IO devices.
|
252
|
+
#
|
253
|
+
# The block will be instance-evaluated at build-time, so it is possible to use
|
254
|
+
# instance variables of the IO device.
|
255
|
+
def when_read(&block)
|
256
|
+
@read_block = block
|
257
|
+
end
|
258
|
+
|
259
|
+
# Defines the write behaviour of this IO device.
|
260
|
+
#
|
261
|
+
# Expects a block, the return value of which is a string
|
262
|
+
# containing the behaviour of this IO device when a value is written to the IO bus.
|
263
|
+
# Care must be taken to ensure that this functionality does not conflict with that of
|
264
|
+
# any other IO devices.
|
265
|
+
#
|
266
|
+
# The block will be instance-evaluated at build-time, so it is possible to use
|
267
|
+
# instance variables of the IO device.
|
268
|
+
def when_write(&block)
|
269
|
+
@write_block = block
|
270
|
+
end
|
271
|
+
|
272
|
+
# Evaluates the when_setup block of this IO device and returns the resulting string.
|
273
|
+
def setup
|
274
|
+
instance_eval(&@setup_block)
|
275
|
+
end
|
276
|
+
|
277
|
+
# Evaluates the when_read block of this IO device and returns the resulting string.
|
278
|
+
def read
|
279
|
+
instance_eval(&@read_block)
|
280
|
+
end
|
281
|
+
|
282
|
+
# Evaluates the when_write block of this IO device and returns the resulting string.
|
283
|
+
def write
|
284
|
+
instance_eval(&@write_block)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Defines FFI API which will be available to the instance wrapper if this IO device is used.
|
288
|
+
def functions
|
289
|
+
[
|
290
|
+
{"name" => "zemu_io_#{name}_master_puts".to_sym, "args" => [:uint8], "return" => :void},
|
291
|
+
{"name" => "zemu_io_#{name}_master_gets".to_sym, "args" => [], "return" => :uint8},
|
292
|
+
{"name" => "zemu_io_#{name}_buffer_size".to_sym, "args" => [], "return" => :uint64}
|
293
|
+
]
|
294
|
+
end
|
295
|
+
|
188
296
|
# Valid parameters for this object.
|
189
297
|
# Should be extended by subclasses but NOT REPLACED.
|
190
298
|
def params
|
@@ -217,8 +325,80 @@ module Zemu
|
|
217
325
|
#
|
218
326
|
def initialize
|
219
327
|
super
|
220
|
-
|
221
|
-
|
328
|
+
|
329
|
+
when_setup do
|
330
|
+
"SerialBuffer io_#{name}_buffer_master = { .head = 0, .tail = 0 };\n" +
|
331
|
+
"SerialBuffer io_#{name}_buffer_slave = { .head = 0, .tail = 0 };\n" +
|
332
|
+
"\n" +
|
333
|
+
"zusize zemu_io_#{name}_buffer_size(void)\n" +
|
334
|
+
"{\n" +
|
335
|
+
" zusize start = io_#{name}_buffer_slave.head;\n" +
|
336
|
+
" zusize end = io_#{name}_buffer_slave.tail\n;" +
|
337
|
+
" if (end < start) end += ZEMU_IO_SERIAL_BUFFER_SIZE;\n" +
|
338
|
+
" return end - start;\n" +
|
339
|
+
"}\n" +
|
340
|
+
"\n" +
|
341
|
+
"void zemu_io_#{name}_slave_puts(zuint8 val)\n" +
|
342
|
+
"{\n" +
|
343
|
+
" io_#{name}_buffer_slave.buffer[io_#{name}_buffer_slave.tail] = val;\n" +
|
344
|
+
" io_#{name}_buffer_slave.tail++;\n" +
|
345
|
+
" if (io_#{name}_buffer_slave.tail >= ZEMU_IO_SERIAL_BUFFER_SIZE)\n" +
|
346
|
+
" io_#{name}_buffer_slave.tail = 0;\n" +
|
347
|
+
"}\n" +
|
348
|
+
"\n" +
|
349
|
+
"zuint8 zemu_io_#{name}_slave_gets(void)\n" +
|
350
|
+
"{\n" +
|
351
|
+
" zuint8 val = io_#{name}_buffer_master.buffer[io_#{name}_buffer_master.head];\n" +
|
352
|
+
" io_#{name}_buffer_master.head++;\n" +
|
353
|
+
" if (io_#{name}_buffer_master.head >= ZEMU_IO_SERIAL_BUFFER_SIZE)\n" +
|
354
|
+
" io_#{name}_buffer_master.head = 0;\n" +
|
355
|
+
"\n" +
|
356
|
+
" return val;\n" +
|
357
|
+
"}\n" +
|
358
|
+
"\n" +
|
359
|
+
"void zemu_io_#{name}_master_puts(zuint8 val)\n" +
|
360
|
+
"{\n" +
|
361
|
+
" io_#{name}_buffer_master.buffer[io_#{name}_buffer_master.tail] = val;\n" +
|
362
|
+
" io_#{name}_buffer_master.tail++;\n" +
|
363
|
+
" if (io_#{name}_buffer_master.tail >= ZEMU_IO_SERIAL_BUFFER_SIZE)\n" +
|
364
|
+
" io_#{name}_buffer_master.tail = 0;\n" +
|
365
|
+
"}\n" +
|
366
|
+
"\n" +
|
367
|
+
"zuint8 zemu_io_#{name}_master_gets(void)\n" +
|
368
|
+
"{\n" +
|
369
|
+
" zuint8 val = io_#{name}_buffer_slave.buffer[io_#{name}_buffer_slave.head];\n" +
|
370
|
+
" io_#{name}_buffer_slave.head++;\n" +
|
371
|
+
" if (io_#{name}_buffer_slave.head >= ZEMU_IO_SERIAL_BUFFER_SIZE)\n" +
|
372
|
+
" io_#{name}_buffer_slave.head = 0;\n" +
|
373
|
+
"\n" +
|
374
|
+
" return val;\n" +
|
375
|
+
"}\n"
|
376
|
+
end
|
377
|
+
|
378
|
+
when_read do
|
379
|
+
"if (port == #{in_port})\n" +
|
380
|
+
"{\n" +
|
381
|
+
" return zemu_io_#{name}_slave_gets();\n" +
|
382
|
+
"}\n" +
|
383
|
+
"else if (port == #{ready_port})\n" +
|
384
|
+
"{\n" +
|
385
|
+
" if (io_#{name}_buffer_master.head == io_#{name}_buffer_master.tail)\n" +
|
386
|
+
" {\n" +
|
387
|
+
" return 0;\n" +
|
388
|
+
" }\n" +
|
389
|
+
" else\n" +
|
390
|
+
" {\n" +
|
391
|
+
" return 1;\n" +
|
392
|
+
" }\n" +
|
393
|
+
"}\n"
|
394
|
+
end
|
395
|
+
|
396
|
+
when_write do
|
397
|
+
"if (port == #{out_port})\n" +
|
398
|
+
"{\n" +
|
399
|
+
" zemu_io_#{name}_slave_puts(value);\n" +
|
400
|
+
"}\n"
|
401
|
+
end
|
222
402
|
end
|
223
403
|
|
224
404
|
# Valid parameters for a SerialPort, along with those
|
data/lib/zemu/instance.rb
CHANGED
@@ -179,9 +179,11 @@ module Zemu
|
|
179
179
|
|
180
180
|
wrapper.attach_function :zemu_debug_get_memory, [:uint16], :uint8
|
181
181
|
|
182
|
-
|
183
|
-
|
184
|
-
|
182
|
+
configuration.io.each do |device|
|
183
|
+
device.functions.each do |f|
|
184
|
+
wrapper.attach_function(f["name"], f["args"], f["return"])
|
185
|
+
end
|
186
|
+
end
|
185
187
|
|
186
188
|
return wrapper
|
187
189
|
end
|
data/src/io.c.erb
CHANGED
@@ -1,83 +1,8 @@
|
|
1
1
|
#include "io.h"
|
2
2
|
|
3
3
|
<% io.each do |device| %>
|
4
|
-
|
5
|
-
/* Buffer to which the master pushes data, slave pulls. */
|
6
|
-
SerialBuffer io_serial_buffer_master = { .head = 0, .tail = 0 };
|
7
|
-
|
8
|
-
/* Buffer to which the slave pushes data, master pulls. */
|
9
|
-
SerialBuffer io_serial_buffer_slave = { .head = 0, .tail = 0 };
|
10
|
-
<% end %>
|
11
|
-
<% end %>
|
12
|
-
|
13
|
-
zusize zemu_io_serial_buffer_size(void)
|
14
|
-
{
|
15
|
-
<% unless io.empty? %>
|
16
|
-
zusize start = io_serial_buffer_slave.head;
|
17
|
-
zusize end = io_serial_buffer_slave.tail;
|
18
|
-
|
19
|
-
if (end < start)
|
20
|
-
{
|
21
|
-
end += ZEMU_IO_SERIAL_BUFFER_SIZE;
|
22
|
-
}
|
23
|
-
|
24
|
-
return end - start;
|
25
|
-
<% else %>
|
26
|
-
return 0;
|
27
|
-
<% end %>
|
28
|
-
}
|
29
|
-
|
30
|
-
void zemu_io_serial_slave_puts(zuint8 val)
|
31
|
-
{
|
32
|
-
<% unless io.empty? %>
|
33
|
-
io_serial_buffer_slave.buffer[io_serial_buffer_slave.tail] = val;
|
34
|
-
io_serial_buffer_slave.tail++;
|
35
|
-
|
36
|
-
if (io_serial_buffer_slave.tail >= ZEMU_IO_SERIAL_BUFFER_SIZE)
|
37
|
-
io_serial_buffer_slave.tail = 0;
|
38
|
-
<% end %>
|
39
|
-
}
|
40
|
-
|
41
|
-
zuint8 zemu_io_serial_slave_gets(void)
|
42
|
-
{
|
43
|
-
<% unless io.empty? %>
|
44
|
-
zuint8 val = io_serial_buffer_master.buffer[io_serial_buffer_master.head];
|
45
|
-
io_serial_buffer_master.head++;
|
46
|
-
|
47
|
-
if (io_serial_buffer_master.head >= ZEMU_IO_SERIAL_BUFFER_SIZE)
|
48
|
-
io_serial_buffer_master.head = 0;
|
49
|
-
|
50
|
-
return val;
|
51
|
-
<% else %>
|
52
|
-
return 0;
|
53
|
-
<% end %>
|
54
|
-
}
|
55
|
-
|
56
|
-
void zemu_io_serial_master_puts(zuint8 val)
|
57
|
-
{
|
58
|
-
<% unless io.empty? %>
|
59
|
-
io_serial_buffer_master.buffer[io_serial_buffer_master.tail] = val;
|
60
|
-
io_serial_buffer_master.tail++;
|
61
|
-
|
62
|
-
if (io_serial_buffer_master.tail >= ZEMU_IO_SERIAL_BUFFER_SIZE)
|
63
|
-
io_serial_buffer_master.tail = 0;
|
64
|
-
<% end %>
|
65
|
-
}
|
66
|
-
|
67
|
-
zuint8 zemu_io_serial_master_gets(void)
|
68
|
-
{
|
69
|
-
<% unless io.empty? %>
|
70
|
-
zuint8 val = io_serial_buffer_slave.buffer[io_serial_buffer_slave.head];
|
71
|
-
io_serial_buffer_slave.head++;
|
72
|
-
|
73
|
-
if (io_serial_buffer_slave.head >= ZEMU_IO_SERIAL_BUFFER_SIZE)
|
74
|
-
io_serial_buffer_slave.head = 0;
|
75
|
-
|
76
|
-
return val;
|
77
|
-
<% else %>
|
78
|
-
return 0;
|
4
|
+
<%= device.setup %>
|
79
5
|
<% end %>
|
80
|
-
}
|
81
6
|
|
82
7
|
zuint8 zemu_io_in(void * context, zuint16 port)
|
83
8
|
{
|
@@ -87,24 +12,7 @@ zuint8 zemu_io_in(void * context, zuint16 port)
|
|
87
12
|
port &= 0x00FF;
|
88
13
|
|
89
14
|
<% io.each do |device| %>
|
90
|
-
|
91
|
-
if (port == <%= device.in_port %>)
|
92
|
-
{
|
93
|
-
return zemu_io_serial_slave_gets();
|
94
|
-
}
|
95
|
-
|
96
|
-
else if (port == <%= device.ready_port %>)
|
97
|
-
{
|
98
|
-
if (io_serial_buffer_master.head == io_serial_buffer_master.tail)
|
99
|
-
{
|
100
|
-
return 0;
|
101
|
-
}
|
102
|
-
else
|
103
|
-
{
|
104
|
-
return 1;
|
105
|
-
}
|
106
|
-
}
|
107
|
-
<% end %>
|
15
|
+
<%= device.read %>
|
108
16
|
<% end %>
|
109
17
|
return 0;
|
110
18
|
}
|
@@ -117,11 +25,6 @@ void zemu_io_out(void * context, zuint16 port, zuint8 value)
|
|
117
25
|
port &= 0x00FF;
|
118
26
|
|
119
27
|
<% io.each do |device| %>
|
120
|
-
|
121
|
-
if (port == <%= device.out_port %>)
|
122
|
-
{
|
123
|
-
zemu_io_serial_slave_puts(value);
|
124
|
-
}
|
125
|
-
<% end %>
|
28
|
+
<%= device.write %>
|
126
29
|
<% end %>
|
127
30
|
}
|
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.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jay Valentine
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-29 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
|