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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2155a9588f54ef36a46f88d07f6ef7a1cb01a27ef8f8b104a2e1118cddbbdfb6
4
- data.tar.gz: fd698260726fc03616d6f42c72039e9a04e4a34f77f04e2d3832a604e7c1ec64
3
+ metadata.gz: 79900374a7a271fbfc1333290b4078e8e587ebbec09034c9cde520623459fcd4
4
+ data.tar.gz: 6282f2f1d04cf8188d84a058100d7db55d9305c3c577104455ead68195d17adb
5
5
  SHA512:
6
- metadata.gz: da88a0cc1dbbd30c9849b400c2fbfea989ff81f500fb51dd0c2fffd8af81a65fca231ddb1937e51205a4b9a7ac0a72ffa435ad0aa8941d9350b4edd42aca9027
7
- data.tar.gz: 4a430f4fa54f8514d4c41a561e0ca92957d361025ce69ffb77a797a2d12b858b2462543ad5cc0eb8b87cd6d1688fa2c826179bd0255085f9d328de8e8629ab0d
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
- @io_type = :serial
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
- wrapper.attach_function :zemu_io_serial_master_puts, [:uint8], :void
183
- wrapper.attach_function :zemu_io_serial_master_gets, [], :uint8
184
- wrapper.attach_function :zemu_io_serial_buffer_size, [], :uint64
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
- <% if device.io_type == :serial %>
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
- <% if device.io_type == :serial %>
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
- <% if device.io_type == :serial %>
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.1
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-22 00:00:00.000000000 Z
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