zemu 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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