z80 0.1.0 → 0.3.0

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: a5289868d57c23014c7ebf04e4a895cfb66743a55bd158f33802f99b8da91ca8
4
- data.tar.gz: 3d33827c3ea92ef3e6194a9b1f60eb6311763aa421ec0e6e459766f6242ee04b
3
+ metadata.gz: 12b7a66c375de5f9ba5690822fcc76724d082ba22b4bcac8f0f13b3d8af27512
4
+ data.tar.gz: 2fdfab6e59f61340b4f2f72ad6e1ce7e715d5964b47d14cfc16e816e9b798d1e
5
5
  SHA512:
6
- metadata.gz: efffd69b66de491f606dec0271479dad51bd1d8a698582e65c3f566da4448bd0e7c5e5ff8bd04c3fa3ef0f1d8bb9d9434abc820c9b71fc916d5eb842d97834d4
7
- data.tar.gz: 6909aa3c155aa3f957ee71e160efdef14984232042f9f1f918e171598a5bf24958d15a62d4f482c7d44317d850aac58abc153042aa70f7c968439c85b334706b
6
+ metadata.gz: 43d9460da873b3513cb3e7b661fd00fe08de1a3016e9716b6862a5ec726d32ef383c2c260dd1e470459dc1f4f636e10d0fce28f170b036b450ef1f82e47fb5ff
7
+ data.tar.gz: c5b2a9e632ce5f07cfd4b7020bf05205e3c3b3db66026606cf43430b91ef92c028ccff7ff9954b53102d3c9a89518ca962aea4294f3c4e3c4d0ebd457a6ec1a2
@@ -0,0 +1,57 @@
1
+ name: Build and test extension
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - '.github/workflows/build-and-test-extension.yml'
7
+ - 'ext/**'
8
+ - 'lib/**'
9
+ - 'z80.gemspec'
10
+ pull_request:
11
+ paths:
12
+ - '.github/workflows/build-and-test-extension.yml'
13
+ - 'ext/**'
14
+ - 'lib/**'
15
+ - 'z80.gemspec'
16
+
17
+ jobs:
18
+ build-and-test-extension:
19
+ runs-on: ${{matrix.os}}
20
+
21
+ strategy:
22
+ matrix:
23
+ os: [macos-latest, ubuntu-latest]
24
+ ruby-version: ['3.2', '3.1', '3.0', '2.7']
25
+
26
+ steps:
27
+ - uses: actions/checkout@v3
28
+
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{matrix.ruby-version}}
33
+
34
+ - name: Install dependencies (macOS)
35
+ if: startsWith(matrix.os, 'macos')
36
+ run: brew install redcode/zxe/z80
37
+
38
+ - name: Install dependencies (Ubuntu)
39
+ if: startsWith(matrix.os, 'ubuntu')
40
+ run: |
41
+ sudo mkdir -pm700 /root/.gnupg
42
+ sudo mkdir -pm755 /etc/apt/keyrings
43
+ sudo gpg --no-default-keyring --keyring /etc/apt/keyrings/zxe-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys FE214A38D6A0C01D9AF514EE841EA3BD3A7E1487
44
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/zxe-archive-keyring.gpg] https://zxe.io/repos/apt stable main" | sudo tee /etc/apt/sources.list.d/zxe.list
45
+ sudo apt-get update
46
+ sudo apt-get -y install libz80-dev
47
+
48
+ - name: Build gem
49
+ run: gem build z80.gemspec
50
+
51
+ - name: Install gem (macOS)
52
+ if: startsWith(matrix.os, 'macos')
53
+ run: gem install z80*.gem -- --with-Z80-dir=$(brew --prefix)
54
+
55
+ - name: Install gem (Ubuntu)
56
+ if: startsWith(matrix.os, 'ubuntu')
57
+ run: gem install z80*.gem
@@ -0,0 +1,40 @@
1
+ name: Publish gem
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish-gem:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+
14
+ - name: Set up Ruby
15
+ uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: "${{vars.PUBLISH_GEM_RUBY_VERSION}}"
18
+
19
+ - name: Publish to GPR
20
+ env:
21
+ GEM_HOST_API_KEY: "Bearer ${{secrets.GPR_PAT}}"
22
+ OWNER: ${{github.repository_owner}}
23
+ run: |
24
+ mkdir -p $HOME/.gem
25
+ touch $HOME/.gem/credentials
26
+ chmod 0600 $HOME/.gem/credentials
27
+ printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
28
+ gem build *.gemspec
29
+ gem push --key github --host https://rubygems.pkg.github.com/${OWNER} *.gem
30
+
31
+ - name: Publish to RubyGems
32
+ env:
33
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
34
+ run: |
35
+ mkdir -p $HOME/.gem
36
+ touch $HOME/.gem/credentials
37
+ chmod 0600 $HOME/.gem/credentials
38
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
39
+ gem build *.gemspec
40
+ gem push *.gem
data/.gitignore CHANGED
@@ -3,15 +3,17 @@
3
3
  Thumbs.db
4
4
  *.a
5
5
  *.bundle
6
+ *.gem
6
7
  *.o
7
8
  *.so
8
9
  /.bundle/
10
+ /.yardoc/
9
11
  /_yardoc/
10
12
  /coverage/
11
13
  /doc/
12
14
  /pkg/
13
15
  /spec/reports/
14
16
  /tmp/
17
+ /.ruby-gemset
15
18
  /.ruby-version
16
- /.yardoc
17
19
  /Gemfile.lock
data/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Z80-Ruby ChangeLog
2
2
 
3
+ ## 0.3.0 / 2024-01-03
4
+
5
+ ### Enhancements
6
+
7
+ * Added `Z80#sf?`, `Z80#zf?`, `Z80#yf?`, `Z80#hf?`, `Z80#xf?`, `Z80#pf?`, `Z80#nf?`, `Z80#cf?`, `Z80#iff1?`, `Z80#iff2?`, `Z80#int_line?` and `Z80#halt_line?`.
8
+ * Changed `Z80#sf`, `Z80#zf`, `Z80#yf`, `Z80#hf`, `Z80#xf`, `Z80#pf`, `Z80#nf` and `Z80#cf` to return an Integer instead of a boolean.
9
+ * The parameter of `Z80#power` is now optional and the default value is `true`.
10
+ * `Z80#to_h` now accepts one optional parameter. Passing `true` will create a Hash with boolean values for the following keys: `:iff1`, `:iff2`, `:int_line` and `:halt_line`.
11
+
12
+ ### Bugfixes
13
+
14
+ * Fixed a potential bug or error when compiling the extension for Ruby `< 3.0`.
15
+
16
+ ## 0.2.0 / 2024-01-02
17
+
18
+ ### Enhancements
19
+
20
+ * Added [`Z80::MINIMUM_CYCLES_PER_STEP`](https://zxe.io/software/Z80/documentation/latest/APIReference.html#c.Z80_MINIMUM_CYCLES_PER_STEP).
21
+ * Minor code improvements.
22
+
23
+ ### Bugfixes
24
+
25
+ * Changed the order in which the files are required so that the extension is loaded before `'z80/version'`.
26
+ * Fixed typos in the names of `Z80#xyl`, `Z80#xyl=`, `Z80#wzh`, `Z80#wzh=`, `Z80#wzl` and `Z80#wzl=`.
27
+
28
+ ### Project
29
+
30
+ * Added CI.
31
+ * Added `Gemfile`, `CITATION.cff`.
32
+ * Added [rake-compiler](https://rubygems.org/gems/rake-compiler) as a development dependency.
33
+
3
34
  ## 0.1.0 / 2023-12-24
4
35
 
5
36
  Initial public release.
data/CITATION.cff ADDED
@@ -0,0 +1,24 @@
1
+ abstract: Ruby interface for the Z80 library.
2
+ authors:
3
+ - family-names: "Sainz de Baranda y Goñi"
4
+ given-names: Manuel
5
+ orcid: https://orcid.org/0000-0001-6326-3519
6
+ email: manuel@zxe.io
7
+ website: https://zxe.io
8
+ cff-version: 1.2.0
9
+ date-released: 2024-01-03
10
+ keywords:
11
+ - binding
12
+ - CPU
13
+ - emulator
14
+ - LLE
15
+ - Ruby
16
+ - Z80
17
+ - Zilog
18
+ license: MIT
19
+ message: If you use this software, please cite it using these metadata.
20
+ repository-code: https://github.com/redcode/Z80-Ruby
21
+ title: Z80-Ruby
22
+ type: software
23
+ version: 0.3.0
24
+ url: https://zxe.io/software/Z80-Ruby
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE-0BSD CHANGED
@@ -1,6 +1,6 @@
1
1
  BSD Zero Clause License
2
2
 
3
- Copyright (C) 2023 Manuel Sainz de Baranda y Goñi.
3
+ Copyright (C) 2023-2024 Manuel Sainz de Baranda y Goñi.
4
4
 
5
5
  Permission to use, copy, modify, and/or distribute this software for any
6
6
  purpose with or without fee is hereby granted.
data/README.md CHANGED
@@ -1,33 +1,57 @@
1
- # Z80-Ruby
1
+ # Z80-Ruby <img src="https://zxe.io/software/Z80-Ruby/assets/images/Z80-Ruby.svg" width="128" align="right">
2
+
3
+ [![](https://zxe.io/software/Z80-Ruby/assets/images/gem-badge)](https://zxe.io/software/Z80-Ruby/gem)
4
+ [![](https://github.com/redcode/Z80-Ruby/actions/workflows/build-and-test-extension.yml/badge.svg)](https://github.com/redcode/Z80-Ruby/actions/workflows/build-and-test-extension.yml)
5
+ [![](https://zxe.io/software/Z80/assets/images/chat-badge)](https://zxe.io/software/Z80/chat)
2
6
 
3
7
  Ruby binding for the [Z80](https://github.com/redcode/Z80) library.
4
8
 
5
9
  ## Installation
6
10
 
7
- First make sure that you have the Z80 library [installed](https://github.com/redcode/Z80#installation) on your system.
11
+ First, make sure that you have the Z80 library [installed](https://github.com/redcode/Z80#installation) on your system.
8
12
 
9
- Then add `z80` to the `Gemfile` of your project and run `bundle`:
13
+ Then add the `z80` gem to the `Gemfile` of your project and run `bundle`:
10
14
 
11
15
  ```ruby
12
16
  gem 'z80'
13
17
  ```
14
18
 
15
- Or install the gem directly with `gem`:
19
+ Or install the gem directly:
16
20
 
17
21
  ```shell
18
22
  gem install z80
19
23
  ```
20
24
 
25
+ ### Troubleshooting
26
+
27
+ #### "I installed the Z80 library through Homebrew, but `bundle` does not find it."
28
+
29
+ Configure the environment variables [`C_INCLUDE_PATH`](https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html#index-C_005fINCLUDE_005fPATH) and [`LIBRARY_PATH`](https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html#index-LIBRARY_005fPATH) by adding the installation prefix of the library:
30
+
31
+ ```shell
32
+ export C_INCLUDE_PATH="$C_INCLUDE_PATH:$(brew --prefix)/include"
33
+ export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"
34
+ ```
35
+
36
+ #### "I installed the Z80 library through Homebrew, but `gem` does not find it."
37
+
38
+ Tell `gem` the installation prefix of the library:
39
+
40
+ ```shell
41
+ gem install z80 -- --with-Z80-dir=$(brew --prefix)
42
+ ```
43
+
21
44
  ## Examples
22
45
 
23
- This small script demonstrates how to run the [CP/M version of ZEXALL](https://github.com/redcode/Z80/wiki/Z80-Instruction-Set-Exerciser) with a few lines of code:
46
+ ### Z80 Instruction Set Exerciser
47
+
48
+ This small script demonstrates how to run the [CP/M versions of `zexall` and `zexdoc`](https://github.com/redcode/Z80/wiki/Z80-Instruction-Set-Exerciser) with a few lines of code:
24
49
 
25
50
  ```ruby
26
51
  require 'z80'
27
52
 
28
- quit = false
29
- memory = Array.new(65536, 0)
30
- cpu = Z80.new
53
+ memory = quit = nil
54
+ cpu = Z80.new
31
55
 
32
56
  cpu.fetch_opcode = cpu.fetch = cpu.read do |context, address|
33
57
  memory[address]
@@ -55,16 +79,32 @@ cpu.hook do |context, address|
55
79
  end
56
80
  end
57
81
 
58
- program = File.read(ARGV[0])
59
- memory[0x0100, program.size] = program.bytes
60
- memory[0] = memory[5] = Z80::HOOK
61
- cpu.power true
62
- cpu.pc = 0x0100
63
- cpu.run(Z80::MAXIMUM_CYCLES) until quit
64
- puts
82
+ $stdout.sync = true if $stdout.tty?
83
+
84
+ ARGV.each do |file_path|
85
+ program = file_path == '-' ? $stdin.read : File.read(file_path)
86
+ puts "#{file_path}:"
87
+ quit = false
88
+ memory = Array.new(65536, 0)
89
+ memory[0x0100, program.size] = program.bytes
90
+ memory[0] = memory[5] = Z80::HOOK
91
+ cpu.power true
92
+ cpu.pc = 0x0100
93
+ cpu.run(Z80::MAXIMUM_CYCLES) until quit
94
+ puts
95
+ break if file_path == '-'
96
+ end
97
+ ```
98
+
99
+ <sup>**[<sub><img src="https://zxe.io/software/Z80-Ruby/assets/images/rb.svg" height="14"></sub> run-yaze-zex.rb](https://zxe.io/software/Z80-Ruby/scripts/run-yaze-zex.rb)**</sup>
100
+
101
+ Want to try it? Use this:
102
+
103
+ ```shell
104
+ curl ftp://ftp.ping.de/pub/misc/emulators/yaze-1.14.tar.gz | tar -xOzf- yaze-1.14/test/zexall.com | ruby -e'eval `curl https://zxe.io/software/Z80-Ruby/scripts/run-yaze-zex.rb`' -
65
105
  ```
66
106
 
67
- <sup>**[<sub><img src="https://zxe.io/software/Z80/assets/images/ruby-icon.svg" height="14"></sub> run-yaze-zexall.rb](https://zxe.io/software/Z80/scripts/run-yaze-zexall.rb)**</sup>
107
+ ### Zilog Z80 CPU Test Suite
68
108
 
69
109
  This runs any tape from Patrik Rak's [Zilog Z80 CPU Test Suite](https://github.com/raxoft/z80test) (except `z80ccfscr.tap`):
70
110
 
@@ -77,11 +117,8 @@ module Opcode
77
117
  CALL = 0xCD
78
118
  end
79
119
 
80
- quit = false
81
- tab = 0
82
- cursor_x = 0
83
- memory = Array.new(65536, 0)
84
- cpu = Z80.new
120
+ quit = cursor_x = tab = memory = nil
121
+ cpu = Z80.new
85
122
 
86
123
  cpu.fetch_opcode = cpu.fetch = cpu.read do |context, address|
87
124
  memory[address]
@@ -135,29 +172,44 @@ cpu.hook do |context, address|
135
172
  end
136
173
  end
137
174
 
138
- program = File.read(ARGV[0])
139
- memory[0x8000, program.size - 91] = program.bytes[91..-1]
140
- memory[0x0010] = Z80::HOOK # THE 'PRINT A CHARACTER' RESTART
141
- memory[0x0D6B] = Opcode::RET # THE 'CLS' COMMAND ROUTINE
142
- memory[0x1601] = Opcode::RET # THE 'CHAN_OPEN' SUBROUTINE
143
- memory[0x7000] = Opcode::CALL # -.
144
- memory[0x7001] = 0x00 # |- call 8000h
145
- memory[0x7002] = 0x80 # -'
146
- memory[0x7003] = Z80::HOOK
147
- cpu.power true
148
- cpu.im = 1
149
- cpu.i = 0x3F
150
- cpu.pc = 0x7000
151
- cpu.run(Z80::MAXIMUM_CYCLES) until quit
175
+ $stdout.sync = true if $stdout.tty?
176
+
177
+ ARGV.each do |file_path|
178
+ program = file_path == '-' ? $stdin.read : File.read(file_path)
179
+ puts "#{file_path}:"
180
+ quit = false
181
+ cursor_x = tab = 0
182
+ memory = Array.new(65536, 0)
183
+ memory[0x8000, program.size - 91] = program.bytes[91..-1]
184
+ memory[0x0010] = Z80::HOOK # THE 'PRINT A CHARACTER' RESTART
185
+ memory[0x0D6B] = Opcode::RET # THE 'CLS' COMMAND ROUTINE
186
+ memory[0x1601] = Opcode::RET # THE 'CHAN_OPEN' SUBROUTINE
187
+ memory[0x7000] = Opcode::CALL # -.
188
+ memory[0x7001] = 0x00 # |- call 8000h
189
+ memory[0x7002] = 0x80 # -'
190
+ memory[0x7003] = Z80::HOOK
191
+ cpu.power true
192
+ cpu.im = 1
193
+ cpu.i = 0x3F
194
+ cpu.pc = 0x7000
195
+ cpu.run(Z80::MAXIMUM_CYCLES) until quit
196
+ break if file_path == '-'
197
+ end
152
198
  ```
153
199
 
154
- <sup>**[<sub><img src="https://zxe.io/software/Z80/assets/images/ruby-icon.svg" height="14"></sub> run-raxoft-z80test.rb](https://zxe.io/software/Z80/scripts/run-raxoft-z80test.rb)**</sup>
200
+ <sup>**[<sub><img src="https://zxe.io/software/Z80-Ruby/assets/images/rb.svg" height="14"></sub> run-raxoft-z80test.rb](https://zxe.io/software/Z80-Ruby/scripts/run-raxoft-z80test.rb)**</sup>
201
+
202
+ Want to try it? Use this:
203
+
204
+ ```shell
205
+ curl http://zxds.raxoft.cz/taps/misc/z80test-1.2a.zip | bsdtar -xOf- z80test-1.2a/z80full.tap | ruby -e'eval `curl https://zxe.io/software/Z80-Ruby/scripts/run-raxoft-z80test.rb`' -
206
+ ```
155
207
 
156
208
  ## License
157
209
 
158
- <img src="https://zxe.io/software/Z80/assets/images/0bsd.svg" width="160" align="right">
210
+ <img src="https://zxe.io/software/Z80-Ruby/assets/images/0bsd.svg" width="160" align="right">
159
211
 
160
- Copyright © 2023 Manuel Sainz de Baranda y Goñi.
212
+ Copyright © 2023-2024 Manuel Sainz de Baranda y Goñi.
161
213
 
162
214
  Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
163
215
 
data/Rakefile CHANGED
@@ -1,5 +1,12 @@
1
+ require "bundler/gem_tasks"
1
2
  require 'rake/extensiontask'
2
3
 
4
+ CLOBBER.include(
5
+ '.yardoc',
6
+ 'doc',
7
+ 'pkg'
8
+ )
9
+
3
10
  Rake::ExtensionTask.new('z80') do |ext|
4
11
  ext.lib_dir = 'lib/z80'
5
12
  end
data/ext/z80/extconf.rb CHANGED
@@ -4,94 +4,48 @@ dir_config 'Z80'
4
4
  abort "missing header Z80.h" unless have_header 'Z80.h'
5
5
  abort "missing library Z80" unless have_library 'Z80'
6
6
 
7
- %w(
8
- z80_power
9
- z80_instant_reset
10
- z80_int
11
- z80_nmi
12
- z80_execute
13
- z80_run
14
- ).each do |function|
15
- abort "missing #{function}()" unless have_func function
7
+ %w(power instant_reset int nmi execute run).each do |function|
8
+ abort "missing z80_#{function}()" unless have_func "z80_#{function}"
16
9
  end
17
10
 
18
11
  have_func 'z80_special_reset'
19
12
 
20
- %w(
21
- z80_break
22
- z80_r
23
- z80_refresh_address
24
- z80_in_cycle
25
- z80_out_cycle
26
- ).each do |function|
27
- abort "missing #{function}()" unless have_func(function, 'Z80.h')
13
+ %w(break r refresh_address in_cycle out_cycle).each do |function|
14
+ abort "missing z80_#{function}()" unless have_func("z80_#{function}", 'Z80.h')
28
15
  end
29
16
 
30
17
  %w(
31
- Z80_MAXIMUM_CYCLES
32
- Z80_MAXIMUM_CYCLES_PER_STEP
33
- Z80_MINIMUM_CYCLES_PER_STEP
34
- Z80_HOOK
35
- Z80_OPTION_OUT_VC_255
36
- Z80_OPTION_LD_A_IR_BUG
37
- Z80_OPTION_HALT_SKIP
38
- Z80_OPTION_XQ
39
- Z80_OPTION_IM0_RETX_NOTIFICATIONS
40
- Z80_OPTION_YQ
41
- Z80_MODEL_ZILOG_NMOS
42
- Z80_MODEL_ZILOG_CMOS
43
- Z80_MODEL_NEC_NMOS
44
- Z80_MODEL_ST_CMOS
45
- Z80_REQUEST_REJECT_NMI
46
- Z80_REQUEST_NMI
47
- Z80_REQUEST_INT
48
- Z80_RESUME_HALT
49
- Z80_RESUME_XY
50
- Z80_RESUME_IM0_XY
51
- Z80_MEMPTR
52
- Z80_PC
53
- Z80_SP
54
- Z80_XY
55
- Z80_IX
56
- Z80_IY
57
- Z80_AF
58
- Z80_BC
59
- Z80_DE
60
- Z80_HL
61
- Z80_AF_
62
- Z80_BC_
63
- Z80_DE_
64
- Z80_HL_
65
- Z80_MEMPTRH
66
- Z80_MEMPTRL
67
- Z80_PCH
68
- Z80_PCL
69
- Z80_SPH
70
- Z80_SPL
71
- Z80_XYH
72
- Z80_XYL
73
- Z80_IXH
74
- Z80_IXL
75
- Z80_IYH
76
- Z80_IYL
77
- Z80_A
78
- Z80_F
79
- Z80_B
80
- Z80_C
81
- Z80_D
82
- Z80_E
83
- Z80_H
84
- Z80_L
85
- Z80_A_
86
- Z80_F_
87
- Z80_B_
88
- Z80_C_
89
- Z80_D_
90
- Z80_E_
91
- Z80_H_
92
- Z80_L_
18
+ MAXIMUM_CYCLES
19
+ MAXIMUM_CYCLES_PER_STEP
20
+ MINIMUM_CYCLES_PER_STEP
21
+
22
+ HOOK
23
+
24
+ OPTION_OUT_VC_255
25
+ OPTION_LD_A_IR_BUG
26
+ OPTION_HALT_SKIP
27
+ OPTION_XQ
28
+ OPTION_IM0_RETX_NOTIFICATIONS
29
+ OPTION_YQ
30
+
31
+ MODEL_ZILOG_NMOS
32
+ MODEL_ZILOG_CMOS
33
+ MODEL_NEC_NMOS
34
+ MODEL_ST_CMOS
35
+
36
+ REQUEST_REJECT_NMI
37
+ REQUEST_NMI
38
+ REQUEST_INT
39
+
40
+ RESUME_HALT
41
+ RESUME_XY
42
+ RESUME_IM0_XY
43
+
44
+ MEMPTR PC SP XY IX IY AF BC DE HL AF_ BC_ DE_ HL_
45
+ MEMPTRH MEMPTRL PCH PCL SPH SPL XYH XYL IXH IXL IYH IYL
46
+ A F B C D E H L A_ F_ B_ C_ D_ E_ H_ L_
93
47
  ).each do |macro|
94
- abort "missing #{macro}" unless have_macro(macro, 'Z80.h')
48
+ abort "missing Z80_#{macro}" unless have_macro("Z80_#{macro}", 'Z80.h')
95
49
  end
96
50
 
97
51
  create_makefile "z80/z80"
data/ext/z80/z80.c CHANGED
@@ -3,7 +3,7 @@
3
3
  ____ \/__/ /\_\ __ \\ \/\ \ ______________________________________
4
4
  | /\_____\\_____\\_____\ |
5
5
  | Zilog \/_____//_____//_____/ CPU Emulator - Ruby Binding |
6
- | Copyright (C) 2023 Manuel Sainz de Baranda y Goñi. |
6
+ | Copyright (C) 2023-2024 Manuel Sainz de Baranda y Goñi. |
7
7
  | |
8
8
  | Permission to use, copy, modify, and/or distribute this software |
9
9
  | for any purpose with or without fee is hereby granted. |
@@ -20,6 +20,7 @@
20
20
  '===================================================================*/
21
21
 
22
22
  #include <ruby.h>
23
+ #include <ruby/version.h>
23
24
  #include <Z80.h>
24
25
  #include <Z/macros/array.h>
25
26
  #include <inttypes.h>
@@ -242,129 +243,173 @@ static VALUE Z80__context(VALUE self)
242
243
  }
243
244
 
244
245
 
246
+ #define INTEGER_ACCESSOR(type, member, access, with, converter_affix) \
247
+ \
248
+ static VALUE Z80__##member(VALUE self) \
249
+ { \
250
+ GET_Z80; \
251
+ return converter_affix##2NUM(access(member, with)); \
252
+ } \
253
+ \
254
+ \
255
+ static VALUE Z80__set_##member(VALUE self, VALUE value) \
256
+ { \
257
+ GET_Z80; \
258
+ access(member, with) = (type)NUM2##converter_affix(value); \
259
+ return value; \
260
+ }
261
+
262
+
245
263
  #define MACRO( member, macro) macro(*z80)
246
264
  #define DIRECT(member, macro) z80->member
247
- #define UINT_TO_BOOL(value) value ? Qtrue : Qfalse
248
265
 
249
- #define BOOL_NUM_TO_UINT(value) \
250
- (value == Qfalse ? 0 : (value == Qtrue ? 1 : !!NUM2UINT(value)))
251
-
252
-
253
- #define ACCESSOR(type, member, access, with, c_to_ruby, ruby_to_c) \
254
- \
255
- static VALUE Z80__##member(VALUE self) \
256
- { \
257
- GET_Z80; \
258
- return c_to_ruby(access(member, with)); \
259
- } \
260
- \
261
- \
262
- static VALUE Z80__set_##member(VALUE self, VALUE value) \
263
- { \
264
- GET_Z80; \
265
- access(member, with) = (type)ruby_to_c(value); \
266
- return value; \
267
- }
266
+ INTEGER_ACCESSOR(zusize, cycles, DIRECT, Z_EMPTY, SIZET)
267
+ INTEGER_ACCESSOR(zusize, cycle_limit, DIRECT, Z_EMPTY, SIZET)
268
+ INTEGER_ACCESSOR(zuint16, memptr, MACRO, Z80_MEMPTR, UINT )
269
+ INTEGER_ACCESSOR(zuint16, pc, MACRO, Z80_PC, UINT )
270
+ INTEGER_ACCESSOR(zuint16, sp, MACRO, Z80_SP, UINT )
271
+ INTEGER_ACCESSOR(zuint16, xy, MACRO, Z80_XY, UINT )
272
+ INTEGER_ACCESSOR(zuint16, ix, MACRO, Z80_IX, UINT )
273
+ INTEGER_ACCESSOR(zuint16, iy, MACRO, Z80_IY, UINT )
274
+ INTEGER_ACCESSOR(zuint16, af, MACRO, Z80_AF, UINT )
275
+ INTEGER_ACCESSOR(zuint16, bc, MACRO, Z80_BC, UINT )
276
+ INTEGER_ACCESSOR(zuint16, de, MACRO, Z80_DE, UINT )
277
+ INTEGER_ACCESSOR(zuint16, hl, MACRO, Z80_HL, UINT )
278
+ INTEGER_ACCESSOR(zuint16, af_, MACRO, Z80_AF_, UINT )
279
+ INTEGER_ACCESSOR(zuint16, bc_, MACRO, Z80_BC_, UINT )
280
+ INTEGER_ACCESSOR(zuint16, de_, MACRO, Z80_DE_, UINT )
281
+ INTEGER_ACCESSOR(zuint16, hl_, MACRO, Z80_HL_, UINT )
282
+ INTEGER_ACCESSOR(zuint8, memptrh, MACRO, Z80_MEMPTRH, UINT )
283
+ INTEGER_ACCESSOR(zuint8, memptrl, MACRO, Z80_MEMPTRL, UINT )
284
+ INTEGER_ACCESSOR(zuint8, pch, MACRO, Z80_PCH, UINT )
285
+ INTEGER_ACCESSOR(zuint8, pcl, MACRO, Z80_PCL, UINT )
286
+ INTEGER_ACCESSOR(zuint8, sph, MACRO, Z80_SPH, UINT )
287
+ INTEGER_ACCESSOR(zuint8, spl, MACRO, Z80_SPL, UINT )
288
+ INTEGER_ACCESSOR(zuint8, xyh, MACRO, Z80_XYH, UINT )
289
+ INTEGER_ACCESSOR(zuint8, xyl, MACRO, Z80_XYL, UINT )
290
+ INTEGER_ACCESSOR(zuint8, ixh, MACRO, Z80_IXH, UINT )
291
+ INTEGER_ACCESSOR(zuint8, ixl, MACRO, Z80_IXL, UINT )
292
+ INTEGER_ACCESSOR(zuint8, iyh, MACRO, Z80_IYH, UINT )
293
+ INTEGER_ACCESSOR(zuint8, iyl, MACRO, Z80_IYL, UINT )
294
+ INTEGER_ACCESSOR(zuint8, a, MACRO, Z80_A, UINT )
295
+ INTEGER_ACCESSOR(zuint8, f, MACRO, Z80_F, UINT )
296
+ INTEGER_ACCESSOR(zuint8, b, MACRO, Z80_B, UINT )
297
+ INTEGER_ACCESSOR(zuint8, c, MACRO, Z80_C, UINT )
298
+ INTEGER_ACCESSOR(zuint8, d, MACRO, Z80_D, UINT )
299
+ INTEGER_ACCESSOR(zuint8, e, MACRO, Z80_E, UINT )
300
+ INTEGER_ACCESSOR(zuint8, h, MACRO, Z80_H, UINT )
301
+ INTEGER_ACCESSOR(zuint8, l, MACRO, Z80_L, UINT )
302
+ INTEGER_ACCESSOR(zuint8, a_, MACRO, Z80_A_, UINT )
303
+ INTEGER_ACCESSOR(zuint8, f_, MACRO, Z80_F_, UINT )
304
+ INTEGER_ACCESSOR(zuint8, b_, MACRO, Z80_B_, UINT )
305
+ INTEGER_ACCESSOR(zuint8, c_, MACRO, Z80_C_, UINT )
306
+ INTEGER_ACCESSOR(zuint8, d_, MACRO, Z80_D_, UINT )
307
+ INTEGER_ACCESSOR(zuint8, e_, MACRO, Z80_E_, UINT )
308
+ INTEGER_ACCESSOR(zuint8, h_, MACRO, Z80_H_, UINT )
309
+ INTEGER_ACCESSOR(zuint8, l_, MACRO, Z80_L_, UINT )
310
+ INTEGER_ACCESSOR(zuint8, r, DIRECT, Z_EMPTY, UINT )
311
+ INTEGER_ACCESSOR(zuint8, i, DIRECT, Z_EMPTY, UINT )
312
+ INTEGER_ACCESSOR(zuint8, r7, DIRECT, Z_EMPTY, UINT )
313
+ INTEGER_ACCESSOR(zuint8, im, DIRECT, Z_EMPTY, UINT )
314
+ INTEGER_ACCESSOR(zuint8, request, DIRECT, Z_EMPTY, UINT )
315
+ INTEGER_ACCESSOR(zuint8, resume, DIRECT, Z_EMPTY, UINT )
316
+ INTEGER_ACCESSOR(zuint8, q, DIRECT, Z_EMPTY, UINT )
317
+ INTEGER_ACCESSOR(zuint8, options, DIRECT, Z_EMPTY, UINT )
268
318
 
269
-
270
- ACCESSOR(zusize, cycles, DIRECT, Z_EMPTY, SIZET2NUM, NUM2SIZET )
271
- ACCESSOR(zusize, cycle_limit, DIRECT, Z_EMPTY, SIZET2NUM, NUM2SIZET )
272
- ACCESSOR(zuint16, memptr, MACRO, Z80_MEMPTR, UINT2NUM, NUM2UINT )
273
- ACCESSOR(zuint16, pc, MACRO, Z80_PC, UINT2NUM, NUM2UINT )
274
- ACCESSOR(zuint16, sp, MACRO, Z80_SP, UINT2NUM, NUM2UINT )
275
- ACCESSOR(zuint16, xy, MACRO, Z80_XY, UINT2NUM, NUM2UINT )
276
- ACCESSOR(zuint16, ix, MACRO, Z80_IX, UINT2NUM, NUM2UINT )
277
- ACCESSOR(zuint16, iy, MACRO, Z80_IY, UINT2NUM, NUM2UINT )
278
- ACCESSOR(zuint16, af, MACRO, Z80_AF, UINT2NUM, NUM2UINT )
279
- ACCESSOR(zuint16, bc, MACRO, Z80_BC, UINT2NUM, NUM2UINT )
280
- ACCESSOR(zuint16, de, MACRO, Z80_DE, UINT2NUM, NUM2UINT )
281
- ACCESSOR(zuint16, hl, MACRO, Z80_HL, UINT2NUM, NUM2UINT )
282
- ACCESSOR(zuint16, af_, MACRO, Z80_AF_, UINT2NUM, NUM2UINT )
283
- ACCESSOR(zuint16, bc_, MACRO, Z80_BC_, UINT2NUM, NUM2UINT )
284
- ACCESSOR(zuint16, de_, MACRO, Z80_DE_, UINT2NUM, NUM2UINT )
285
- ACCESSOR(zuint16, hl_, MACRO, Z80_HL_, UINT2NUM, NUM2UINT )
286
- ACCESSOR(zuint8, memptrh, MACRO, Z80_MEMPTRH, UINT2NUM, NUM2UINT )
287
- ACCESSOR(zuint8, memptrl, MACRO, Z80_MEMPTRL, UINT2NUM, NUM2UINT )
288
- ACCESSOR(zuint8, pch, MACRO, Z80_PCH, UINT2NUM, NUM2UINT )
289
- ACCESSOR(zuint8, pcl, MACRO, Z80_PCL, UINT2NUM, NUM2UINT )
290
- ACCESSOR(zuint8, sph, MACRO, Z80_SPH, UINT2NUM, NUM2UINT )
291
- ACCESSOR(zuint8, spl, MACRO, Z80_SPL, UINT2NUM, NUM2UINT )
292
- ACCESSOR(zuint8, xyh, MACRO, Z80_XYH, UINT2NUM, NUM2UINT )
293
- ACCESSOR(zuint8, yl, MACRO, Z80_XYL, UINT2NUM, NUM2UINT )
294
- ACCESSOR(zuint8, ixh, MACRO, Z80_IXH, UINT2NUM, NUM2UINT )
295
- ACCESSOR(zuint8, ixl, MACRO, Z80_IXL, UINT2NUM, NUM2UINT )
296
- ACCESSOR(zuint8, iyh, MACRO, Z80_IYH, UINT2NUM, NUM2UINT )
297
- ACCESSOR(zuint8, iyl, MACRO, Z80_IYL, UINT2NUM, NUM2UINT )
298
- ACCESSOR(zuint8, a, MACRO, Z80_A, UINT2NUM, NUM2UINT )
299
- ACCESSOR(zuint8, f, MACRO, Z80_F, UINT2NUM, NUM2UINT )
300
- ACCESSOR(zuint8, b, MACRO, Z80_B, UINT2NUM, NUM2UINT )
301
- ACCESSOR(zuint8, c, MACRO, Z80_C, UINT2NUM, NUM2UINT )
302
- ACCESSOR(zuint8, d, MACRO, Z80_D, UINT2NUM, NUM2UINT )
303
- ACCESSOR(zuint8, e, MACRO, Z80_E, UINT2NUM, NUM2UINT )
304
- ACCESSOR(zuint8, h, MACRO, Z80_H, UINT2NUM, NUM2UINT )
305
- ACCESSOR(zuint8, l, MACRO, Z80_L, UINT2NUM, NUM2UINT )
306
- ACCESSOR(zuint8, a_, MACRO, Z80_A_, UINT2NUM, NUM2UINT )
307
- ACCESSOR(zuint8, f_, MACRO, Z80_F_, UINT2NUM, NUM2UINT )
308
- ACCESSOR(zuint8, b_, MACRO, Z80_B_, UINT2NUM, NUM2UINT )
309
- ACCESSOR(zuint8, c_, MACRO, Z80_C_, UINT2NUM, NUM2UINT )
310
- ACCESSOR(zuint8, d_, MACRO, Z80_D_, UINT2NUM, NUM2UINT )
311
- ACCESSOR(zuint8, e_, MACRO, Z80_E_, UINT2NUM, NUM2UINT )
312
- ACCESSOR(zuint8, h_, MACRO, Z80_H_, UINT2NUM, NUM2UINT )
313
- ACCESSOR(zuint8, l_, MACRO, Z80_L_, UINT2NUM, NUM2UINT )
314
- ACCESSOR(zuint8, r, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
315
- ACCESSOR(zuint8, i, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
316
- ACCESSOR(zuint8, r7, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
317
- ACCESSOR(zuint8, im, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
318
- ACCESSOR(zuint8, request, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
319
- ACCESSOR(zuint8, resume, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
320
- ACCESSOR(zuint8, iff1, DIRECT, Z_EMPTY, UINT_TO_BOOL, BOOL_NUM_TO_UINT)
321
- ACCESSOR(zuint8, iff2, DIRECT, Z_EMPTY, UINT_TO_BOOL, BOOL_NUM_TO_UINT)
322
- ACCESSOR(zuint8, q, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
323
- ACCESSOR(zuint8, options, DIRECT, Z_EMPTY, UINT2NUM, NUM2UINT )
324
- ACCESSOR(zuint8, int_line, DIRECT, Z_EMPTY, UINT_TO_BOOL, BOOL_NUM_TO_UINT)
325
- ACCESSOR(zuint8, halt_line, DIRECT, Z_EMPTY, UINT_TO_BOOL, BOOL_NUM_TO_UINT)
326
-
327
- #undef UINT_TO_BOOL
328
319
  #undef MACRO
329
320
  #undef DIRECT
330
- #undef ACCESSOR
331
-
332
-
333
- #define FLAG_ACCESSOR(flag, shift) \
334
- \
335
- static VALUE Z80__##flag(VALUE self) \
336
- { \
337
- GET_Z80; \
338
- return UINT2NUM((Z80_F(*z80) >> shift) & 1); \
339
- } \
340
- \
341
- static VALUE Z80__set_##flag(VALUE self, VALUE value) \
342
- { \
343
- zuint8 bit = (zuint8)(NUM2UINT(value) & 1); \
344
- GET_Z80; \
345
- Z80_F(*z80) = (Z80_F(*z80) & ~(1U << shift)) | (bit << shift); \
346
- return UINT2NUM(bit); \
321
+ #undef INTEGER_ACCESSOR
322
+
323
+
324
+ #define BOOL_NUM_TO_UINT(value) \
325
+ (value == Qfalse ? 0U : (value == Qtrue ? 1U : !!NUM2UINT(value)))
326
+
327
+
328
+ #define BOOLEAN_ACCESSOR(member) \
329
+ \
330
+ static VALUE Z80__##member(VALUE self) \
331
+ { \
332
+ GET_Z80; \
333
+ return UINT2NUM(z80->member); \
334
+ } \
335
+ \
336
+ static VALUE Z80__##member##_p(VALUE self) \
337
+ { \
338
+ GET_Z80; \
339
+ return z80->member ? Qtrue : Qfalse; \
340
+ } \
341
+ \
342
+ \
343
+ static VALUE Z80__set_##member(VALUE self, VALUE value) \
344
+ { \
345
+ GET_Z80; \
346
+ z80->member = BOOL_NUM_TO_UINT(value); \
347
+ return value; \
347
348
  }
348
349
 
349
350
 
350
- FLAG_ACCESSOR(sf, 7)
351
- FLAG_ACCESSOR(zf, 6)
352
- FLAG_ACCESSOR(yf, 5)
353
- FLAG_ACCESSOR(hf, 4)
354
- FLAG_ACCESSOR(xf, 3)
355
- FLAG_ACCESSOR(pf, 2)
356
- FLAG_ACCESSOR(nf, 1)
357
- FLAG_ACCESSOR(cf, 0)
351
+ BOOLEAN_ACCESSOR(iff1 )
352
+ BOOLEAN_ACCESSOR(iff2 )
353
+ BOOLEAN_ACCESSOR(int_line )
354
+ BOOLEAN_ACCESSOR(halt_line)
355
+
356
+ #undef BOOLEAN_ACCESSOR
357
+
358
+
359
+ #define FLAG_ACCESSOR(flag, mask, shift) \
360
+ \
361
+ static VALUE Z80__##flag(VALUE self) \
362
+ { \
363
+ GET_Z80; \
364
+ return UINT2NUM((Z80_F(*z80) >> shift) & 1); \
365
+ } \
366
+ \
367
+ \
368
+ static VALUE Z80__##flag##_p(VALUE self) \
369
+ { \
370
+ GET_Z80; \
371
+ return Z80_F(*z80) & Z80_##mask ? Qtrue : Qfalse; \
372
+ } \
373
+ \
374
+ \
375
+ static VALUE Z80__set_##flag(VALUE self, VALUE value) \
376
+ { \
377
+ GET_Z80; \
378
+ \
379
+ Z80_F(*z80) = \
380
+ (Z80_F(*z80) & ~(1U << shift)) | \
381
+ (BOOL_NUM_TO_UINT(value) << shift); \
382
+ \
383
+ return value; \
384
+ }
385
+
386
+
387
+ FLAG_ACCESSOR(sf, SF, 7)
388
+ FLAG_ACCESSOR(zf, ZF, 6)
389
+ FLAG_ACCESSOR(yf, YF, 5)
390
+ FLAG_ACCESSOR(hf, HF, 4)
391
+ FLAG_ACCESSOR(xf, XF, 3)
392
+ FLAG_ACCESSOR(pf, PF, 2)
393
+ FLAG_ACCESSOR(nf, NF, 1)
394
+ FLAG_ACCESSOR(cf, CF, 0)
358
395
 
359
396
  #undef FLAG_ACCESSOR
397
+ #undef BOOL_NUM_TO_UINT
360
398
 
361
399
 
362
400
  /* MARK: - Methods */
363
401
 
364
- static VALUE Z80__power(VALUE self, VALUE state)
402
+ static VALUE Z80__power(int argc, VALUE *argv, VALUE self)
365
403
  {
366
- GET_Z80;
367
- z80_power(z80, RB_TEST(state));
404
+ Z80 *z80;
405
+
406
+ if (argc > 1) rb_raise(
407
+ rb_eArgError,
408
+ "wrong number of arguments (given %d, expected 0 or 1)",
409
+ argc);
410
+
411
+ TypedData_Get_Struct(self, Z80, &z80_data_type, z80);
412
+ z80_power(z80, RB_TEST(argv[0]));
368
413
  return self;
369
414
  }
370
415
 
@@ -445,7 +490,7 @@ static VALUE Z80__out_cycle(VALUE self)
445
490
 
446
491
  static struct {char const* name; zuint offset;} const
447
492
 
448
- members_16[] = {
493
+ uint16_members[] = {
449
494
  {"memptr", Z_MEMBER_OFFSET(Z80, memptr )},
450
495
  {"pc", Z_MEMBER_OFFSET(Z80, pc )},
451
496
  {"sp", Z_MEMBER_OFFSET(Z80, sp )},
@@ -462,39 +507,57 @@ members_16[] = {
462
507
  {"hl_", Z_MEMBER_OFFSET(Z80, hl_ )}
463
508
  },
464
509
 
465
- members_8[] = {
466
- {"r", Z_MEMBER_OFFSET(Z80, r )},
510
+ uint8_members[] = {
467
511
  {"i", Z_MEMBER_OFFSET(Z80, i )},
512
+ {"r", Z_MEMBER_OFFSET(Z80, r )},
468
513
  {"r7", Z_MEMBER_OFFSET(Z80, r7 )},
514
+ {"q", Z_MEMBER_OFFSET(Z80, q )},
469
515
  {"im", Z_MEMBER_OFFSET(Z80, im )},
470
516
  {"request", Z_MEMBER_OFFSET(Z80, request )},
471
517
  {"resume", Z_MEMBER_OFFSET(Z80, resume )},
518
+ {"options", Z_MEMBER_OFFSET(Z80, options )},
472
519
  {"iff1", Z_MEMBER_OFFSET(Z80, iff1 )},
473
520
  {"iff2", Z_MEMBER_OFFSET(Z80, iff2 )},
474
- {"q", Z_MEMBER_OFFSET(Z80, q )},
475
- {"options", Z_MEMBER_OFFSET(Z80, options )},
476
521
  {"int_line", Z_MEMBER_OFFSET(Z80, int_line )},
477
522
  {"halt_line", Z_MEMBER_OFFSET(Z80, halt_line)}
478
523
  };
479
524
 
480
525
 
481
- static VALUE Z80__to_h(VALUE self)
526
+ static VALUE Z80__to_h(int argc, VALUE *argv, VALUE self)
482
527
  {
483
- VALUE hash = rb_hash_new();
484
- VALUE kv[(Z_ARRAY_SIZE(members_16) + Z_ARRAY_SIZE(members_8)) * 2];
485
- int i = 0, j;
486
- GET_Z80;
528
+ Z80 *z80;
529
+ VALUE hash;
530
+ VALUE kv[(Z_ARRAY_SIZE(uint16_members) + Z_ARRAY_SIZE(uint8_members)) * 2];
531
+ int i, j, uint8_member_count;
487
532
 
488
- for (j = 0; j < Z_ARRAY_SIZE(members_16);)
533
+ if (argc > 1) rb_raise(
534
+ rb_eArgError,
535
+ "wrong number of arguments (given %d, expected 0 or 1)",
536
+ argc);
537
+
538
+ TypedData_Get_Struct(self, Z80, &z80_data_type, z80);
539
+ hash = rb_hash_new();
540
+
541
+ uint8_member_count =
542
+ Z_ARRAY_SIZE(uint8_members) -
543
+ ((argc && RB_TEST(argv[0])) << 2); /* 4 or 0 */
544
+
545
+ for (i = j = 0; j < Z_ARRAY_SIZE(uint16_members);)
489
546
  {
490
- kv[i++] = rb_id2sym(rb_intern(members_16[j].name));
491
- kv[i++] = UINT2NUM(*(zuint16 *)(void *)((char *)z80 + members_16[j++].offset));
547
+ kv[i++] = rb_id2sym(rb_intern(uint16_members[j].name));
548
+ kv[i++] = UINT2NUM(*(zuint16 *)(void *)((char *)z80 + uint16_members[j++].offset));
492
549
  }
493
550
 
494
- for (j = 0; j < Z_ARRAY_SIZE(members_8);)
551
+ for (j = 0; j < uint8_member_count;)
495
552
  {
496
- kv[i++] = rb_id2sym(rb_intern(members_8[j].name));
497
- kv[i++] = UINT2NUM(*((zuint8 *)z80 + members_8[j++].offset));
553
+ kv[i++] = rb_id2sym(rb_intern(uint8_members[j].name));
554
+ kv[i++] = UINT2NUM(*((zuint8 *)z80 + uint8_members[j++].offset));
555
+ }
556
+
557
+ while (j < Z_ARRAY_SIZE(uint8_members))
558
+ {
559
+ kv[i++] = rb_id2sym(rb_intern(uint8_members[j].name));
560
+ kv[i++] = *((zuint8 *)z80 + uint8_members[j++].offset) ? Qtrue : Qfalse;
498
561
  }
499
562
 
500
563
  rb_hash_bulk_insert_into_st_table(Z_ARRAY_SIZE(kv), kv, hash);
@@ -529,7 +592,7 @@ static VALUE Z80__print(VALUE self)
529
592
  "%c %c %c %c %c %c %c %c IFF2 %" PRIu8 " R7 %" PRIu8 " RI %" PRIu8 "\n",
530
593
  Z80_PC(*z80), Z80_AF(*z80), Z80_AF_(*z80), Z80_IX(*z80),
531
594
  Z80_SP(*z80), Z80_BC(*z80), Z80_BC_(*z80), Z80_IY(*z80),
532
- z80->i, z80->r, Z80_DE(*z80), Z80_DE_(*z80), Z80_IX(*z80),
595
+ z80->i, z80->r, Z80_DE(*z80), Z80_DE_(*z80), Z80_IX(*z80),
533
596
  Z80_MEMPTR(*z80), Z80_HL(*z80), Z80_HL_(*z80), z80->q,
534
597
  z80->iff1, z80->im, '\0',
535
598
  one_hyphen[!(f & Z80_SF)],
@@ -580,13 +643,13 @@ static void Z80__compact(Z80 *z80)
580
643
  static rb_data_type_t const z80_data_type = {
581
644
  .wrap_struct_name = "z80",
582
645
  .function = {
583
- .dmark = (void (*)(void *))Z80__mark,
584
- .dfree = (void (*)(void *))Z80__free,
585
- .dsize = NULL,
586
- .dcompact = (void (*)(void *))Z80__compact
587
- },
588
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
589
- };
646
+ # if defined(RUBY_API_VERSION_MAJOR) && RUBY_API_VERSION_MAJOR >= 3
647
+ .dcompact = (void (*)(void *))Z80__compact,
648
+ # endif
649
+ .dmark = (void (*)(void *))Z80__mark,
650
+ .dfree = (void (*)(void *))Z80__free,
651
+ .dsize = NULL},
652
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
590
653
 
591
654
 
592
655
  static VALUE Z80__alloc(VALUE klass)
@@ -608,7 +671,7 @@ static VALUE Z80__alloc(VALUE klass)
608
671
  z80->nop =
609
672
  z80->nmia =
610
673
  z80->inta =
611
- z80->int_fetch =
674
+ z80->int_fetch =
612
675
  z80->hook = NULL;
613
676
  z80->ld_i_a =
614
677
  z80->ld_r_a =
@@ -624,7 +687,7 @@ static VALUE Z80__alloc(VALUE klass)
624
687
 
625
688
  void Init_z80(void)
626
689
  {
627
- VALUE module, klass = rb_const_get(rb_cObject, rb_intern("Z80"));
690
+ VALUE module, klass = rb_define_class("Z80", rb_cObject);
628
691
 
629
692
  rb_define_alloc_func(klass, Z80__alloc);
630
693
 
@@ -670,107 +733,113 @@ void Init_z80(void)
670
733
  rb_define_const(module, "XY", UINT2NUM(Z80_RESUME_XY ));
671
734
  rb_define_const(module, "IM0_XY", UINT2NUM(Z80_RESUME_IM0_XY));
672
735
 
673
- # define DEFINE_ACCESSOR(name, getter_arity) \
674
- rb_define_method(klass, #name, Z80__##name, getter_arity); \
736
+ # define DEFINE_ACCESSOR(name) \
737
+ rb_define_method(klass, #name, Z80__##name, 0); \
675
738
  rb_define_method(klass, #name "=", Z80__set_##name, 1);
676
739
 
677
- DEFINE_ACCESSOR(fetch_opcode, 0)
678
- DEFINE_ACCESSOR(fetch, 0)
679
- DEFINE_ACCESSOR(read, 0)
680
- DEFINE_ACCESSOR(write, 0)
681
- DEFINE_ACCESSOR(in, 0)
682
- DEFINE_ACCESSOR(out, 0)
683
- DEFINE_ACCESSOR(halt, 0)
684
- DEFINE_ACCESSOR(nop, 0)
685
- DEFINE_ACCESSOR(nmia, 0)
686
- DEFINE_ACCESSOR(inta, 0)
687
- DEFINE_ACCESSOR(int_fetch, 0)
688
- DEFINE_ACCESSOR(ld_i_a, 0)
689
- DEFINE_ACCESSOR(ld_r_a, 0)
690
- DEFINE_ACCESSOR(reti, 0)
691
- DEFINE_ACCESSOR(retn, 0)
692
- DEFINE_ACCESSOR(hook, 0)
693
- DEFINE_ACCESSOR(illegal, 0)
694
- DEFINE_ACCESSOR(context, 0)
695
- DEFINE_ACCESSOR(cycles, 0)
696
- DEFINE_ACCESSOR(cycle_limit, 0)
697
- DEFINE_ACCESSOR(memptr, 0)
698
- DEFINE_ACCESSOR(pc, 0)
699
- DEFINE_ACCESSOR(sp, 0)
700
- DEFINE_ACCESSOR(xy, 0)
701
- DEFINE_ACCESSOR(ix, 0)
702
- DEFINE_ACCESSOR(iy, 0)
703
- DEFINE_ACCESSOR(af, 0)
704
- DEFINE_ACCESSOR(bc, 0)
705
- DEFINE_ACCESSOR(de, 0)
706
- DEFINE_ACCESSOR(hl, 0)
707
- DEFINE_ACCESSOR(af_, 0)
708
- DEFINE_ACCESSOR(bc_, 0)
709
- DEFINE_ACCESSOR(de_, 0)
710
- DEFINE_ACCESSOR(hl_, 0)
711
- DEFINE_ACCESSOR(memptrh, 0)
712
- DEFINE_ACCESSOR(memptrl, 0)
713
- DEFINE_ACCESSOR(pch, 0)
714
- DEFINE_ACCESSOR(pcl, 0)
715
- DEFINE_ACCESSOR(sph, 0)
716
- DEFINE_ACCESSOR(spl, 0)
717
- DEFINE_ACCESSOR(xyh, 0)
718
- DEFINE_ACCESSOR(yl, 0)
719
- DEFINE_ACCESSOR(ixh, 0)
720
- DEFINE_ACCESSOR(ixl, 0)
721
- DEFINE_ACCESSOR(iyh, 0)
722
- DEFINE_ACCESSOR(iyl, 0)
723
- DEFINE_ACCESSOR(a, 0)
724
- DEFINE_ACCESSOR(f, 0)
725
- DEFINE_ACCESSOR(b, 0)
726
- DEFINE_ACCESSOR(c, 0)
727
- DEFINE_ACCESSOR(d, 0)
728
- DEFINE_ACCESSOR(e, 0)
729
- DEFINE_ACCESSOR(h, 0)
730
- DEFINE_ACCESSOR(l, 0)
731
- DEFINE_ACCESSOR(a_, 0)
732
- DEFINE_ACCESSOR(f_, 0)
733
- DEFINE_ACCESSOR(b_, 0)
734
- DEFINE_ACCESSOR(c_, 0)
735
- DEFINE_ACCESSOR(d_, 0)
736
- DEFINE_ACCESSOR(e_, 0)
737
- DEFINE_ACCESSOR(h_, 0)
738
- DEFINE_ACCESSOR(l_, 0)
739
- DEFINE_ACCESSOR(r, 0)
740
- DEFINE_ACCESSOR(i, 0)
741
- DEFINE_ACCESSOR(r7, 0)
742
- DEFINE_ACCESSOR(im, 0)
743
- DEFINE_ACCESSOR(request, 0)
744
- DEFINE_ACCESSOR(resume, 0)
745
- DEFINE_ACCESSOR(iff1, 0)
746
- DEFINE_ACCESSOR(iff2, 0)
747
- DEFINE_ACCESSOR(q, 0)
748
- DEFINE_ACCESSOR(options, 0)
749
- DEFINE_ACCESSOR(int_line, 0)
750
- DEFINE_ACCESSOR(halt_line, 0)
751
- DEFINE_ACCESSOR(sf, 0)
752
- DEFINE_ACCESSOR(zf, 0)
753
- DEFINE_ACCESSOR(yf, 0)
754
- DEFINE_ACCESSOR(hf, 0)
755
- DEFINE_ACCESSOR(xf, 0)
756
- DEFINE_ACCESSOR(pf, 0)
757
- DEFINE_ACCESSOR(nf, 0)
758
- DEFINE_ACCESSOR(cf, 0)
740
+ DEFINE_ACCESSOR(fetch_opcode)
741
+ DEFINE_ACCESSOR(fetch )
742
+ DEFINE_ACCESSOR(read )
743
+ DEFINE_ACCESSOR(write )
744
+ DEFINE_ACCESSOR(in )
745
+ DEFINE_ACCESSOR(out )
746
+ DEFINE_ACCESSOR(halt )
747
+ DEFINE_ACCESSOR(nop )
748
+ DEFINE_ACCESSOR(nmia )
749
+ DEFINE_ACCESSOR(inta )
750
+ DEFINE_ACCESSOR(int_fetch )
751
+ DEFINE_ACCESSOR(ld_i_a )
752
+ DEFINE_ACCESSOR(ld_r_a )
753
+ DEFINE_ACCESSOR(reti )
754
+ DEFINE_ACCESSOR(retn )
755
+ DEFINE_ACCESSOR(hook )
756
+ DEFINE_ACCESSOR(illegal )
757
+ DEFINE_ACCESSOR(context )
758
+ DEFINE_ACCESSOR(cycles )
759
+ DEFINE_ACCESSOR(cycle_limit )
760
+ DEFINE_ACCESSOR(memptr )
761
+ DEFINE_ACCESSOR(pc )
762
+ DEFINE_ACCESSOR(sp )
763
+ DEFINE_ACCESSOR(xy )
764
+ DEFINE_ACCESSOR(ix )
765
+ DEFINE_ACCESSOR(iy )
766
+ DEFINE_ACCESSOR(af )
767
+ DEFINE_ACCESSOR(bc )
768
+ DEFINE_ACCESSOR(de )
769
+ DEFINE_ACCESSOR(hl )
770
+ DEFINE_ACCESSOR(af_ )
771
+ DEFINE_ACCESSOR(bc_ )
772
+ DEFINE_ACCESSOR(de_ )
773
+ DEFINE_ACCESSOR(hl_ )
774
+ DEFINE_ACCESSOR(memptrh )
775
+ DEFINE_ACCESSOR(memptrl )
776
+ DEFINE_ACCESSOR(pch )
777
+ DEFINE_ACCESSOR(pcl )
778
+ DEFINE_ACCESSOR(sph )
779
+ DEFINE_ACCESSOR(spl )
780
+ DEFINE_ACCESSOR(xyh )
781
+ DEFINE_ACCESSOR(xyl )
782
+ DEFINE_ACCESSOR(ixh )
783
+ DEFINE_ACCESSOR(ixl )
784
+ DEFINE_ACCESSOR(iyh )
785
+ DEFINE_ACCESSOR(iyl )
786
+ DEFINE_ACCESSOR(a )
787
+ DEFINE_ACCESSOR(f )
788
+ DEFINE_ACCESSOR(b )
789
+ DEFINE_ACCESSOR(c )
790
+ DEFINE_ACCESSOR(d )
791
+ DEFINE_ACCESSOR(e )
792
+ DEFINE_ACCESSOR(h )
793
+ DEFINE_ACCESSOR(l )
794
+ DEFINE_ACCESSOR(a_ )
795
+ DEFINE_ACCESSOR(f_ )
796
+ DEFINE_ACCESSOR(b_ )
797
+ DEFINE_ACCESSOR(c_ )
798
+ DEFINE_ACCESSOR(d_ )
799
+ DEFINE_ACCESSOR(e_ )
800
+ DEFINE_ACCESSOR(h_ )
801
+ DEFINE_ACCESSOR(l_ )
802
+ DEFINE_ACCESSOR(r )
803
+ DEFINE_ACCESSOR(i )
804
+ DEFINE_ACCESSOR(r7 )
805
+ DEFINE_ACCESSOR(im )
806
+ DEFINE_ACCESSOR(request )
807
+ DEFINE_ACCESSOR(resume )
808
+ DEFINE_ACCESSOR(q )
809
+ DEFINE_ACCESSOR(options )
810
+
811
+ # define DEFINE_BOOLEAN_ACCESSOR(name) \
812
+ DEFINE_ACCESSOR(name) \
813
+ rb_define_method(klass, #name "?", Z80__##name##_p, 0);
814
+
815
+ DEFINE_BOOLEAN_ACCESSOR(iff1 )
816
+ DEFINE_BOOLEAN_ACCESSOR(iff2 )
817
+ DEFINE_BOOLEAN_ACCESSOR(int_line )
818
+ DEFINE_BOOLEAN_ACCESSOR(halt_line)
819
+ DEFINE_BOOLEAN_ACCESSOR(sf )
820
+ DEFINE_BOOLEAN_ACCESSOR(zf )
821
+ DEFINE_BOOLEAN_ACCESSOR(yf )
822
+ DEFINE_BOOLEAN_ACCESSOR(hf )
823
+ DEFINE_BOOLEAN_ACCESSOR(xf )
824
+ DEFINE_BOOLEAN_ACCESSOR(pf )
825
+ DEFINE_BOOLEAN_ACCESSOR(nf )
826
+ DEFINE_BOOLEAN_ACCESSOR(cf )
759
827
 
760
828
  # undef DEFINE_ACCESSOR
829
+ # undef DEFINE_FLAG_ACCESSOR
761
830
 
762
- rb_define_method(klass, "power", Z80__power, 1);
831
+ rb_define_method(klass, "power", Z80__power, -1);
763
832
  rb_define_method(klass, "instant_reset", Z80__instant_reset, 0);
764
833
  rb_define_method(klass, "int", Z80__int, 1);
765
834
  rb_define_method(klass, "nmi", Z80__nmi, 0);
766
835
  rb_define_method(klass, "execute", Z80__execute, 1);
767
836
  rb_define_method(klass, "run", Z80__run, 1);
768
837
  rb_define_method(klass, "terminate", Z80__terminate, 0);
769
- rb_define_method(klass, "full_r", Z80__refresh_address, 0);
838
+ rb_define_method(klass, "full_r", Z80__refresh_address, 0);
770
839
  rb_define_method(klass, "refresh_address", Z80__refresh_address, 0);
771
840
  rb_define_method(klass, "in_cycle", Z80__in_cycle, 0);
772
841
  rb_define_method(klass, "out_cycle", Z80__out_cycle, 0);
773
- rb_define_method(klass, "to_h", Z80__to_h, 0);
842
+ rb_define_method(klass, "to_h", Z80__to_h, -1);
774
843
  rb_define_method(klass, "print", Z80__print, 0);
775
844
  /* rb_define_method(klass, "to_s", Z80__to_s, 0);*/
776
845
 
@@ -778,10 +847,10 @@ void Init_z80(void)
778
847
  rb_define_alias(klass, "t=", "cycles=" );
779
848
  rb_define_alias(klass, "wz", "memptr" );
780
849
  rb_define_alias(klass, "wz=", "memptr=" );
781
- rb_define_alias(klass, "w", "memptrh" );
782
- rb_define_alias(klass, "w=", "memptrh=");
783
- rb_define_alias(klass, "z", "memptrl" );
784
- rb_define_alias(klass, "z=", "memptrl=");
850
+ rb_define_alias(klass, "wzh", "memptrh" );
851
+ rb_define_alias(klass, "wzh=", "memptrh=");
852
+ rb_define_alias(klass, "wzl", "memptrl" );
853
+ rb_define_alias(klass, "wzl=", "memptrl=");
785
854
  rb_define_alias(klass, "vf", "pf" );
786
855
  rb_define_alias(klass, "vf=", "pf=" );
787
856
  rb_define_alias(klass, "state", "to_h" );
data/lib/z80/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Z80
2
- VERSION = '0.1.0'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/z80.rb CHANGED
@@ -1,2 +1,2 @@
1
- require 'z80/version'
2
1
  require 'z80/z80'
2
+ require 'z80/version'
data/z80.gemspec ADDED
@@ -0,0 +1,49 @@
1
+ require_relative 'lib/z80/version'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'z80'
5
+ s.version = Z80::VERSION
6
+ s.author = 'Manuel Sainz de Baranda y Goñi'
7
+ s.email = 'manuel@zxe.io'
8
+ s.homepage = 'https://zxe.io/software/Z80-Ruby'
9
+ s.license = '0BSD'
10
+ s.summary = "Ruby binding for the Z80 library."
11
+
12
+ s.description = <<~EOS
13
+ Z80-Ruby is a Ruby binding for the Zilog Z80 CPU emulator \
14
+ (https://github.com/redcode/Z80). It is ideal for analysis, \
15
+ hacking, testing and debugging. All from the comfort of Ruby.
16
+ EOS
17
+
18
+ s.metadata = {
19
+ 'bug_tracker_uri' => "https://github.com/redcode/Z80-Ruby/issues",
20
+ 'changelog_uri' => 'https://github.com/redcode/Z80-Ruby/blob/master/CHANGELOG.md',
21
+ 'documentation_uri' => 'https://zxe.io/software/Z80/documentation/latest',
22
+ 'github_repo' => 'ssh://github.com/redcode/Z80-Ruby',
23
+ 'homepage_uri' => 'https://zxe.io/software/Z80-Ruby',
24
+ 'source_code_uri' => 'https://github.com/redcode/Z80-Ruby'
25
+ }
26
+
27
+ s.files = [
28
+ # `git ls-files | sort`.split("\n")
29
+ '.editorconfig',
30
+ '.github/FUNDING.yml',
31
+ '.github/workflows/build-and-test-extension.yml',
32
+ '.github/workflows/publish-gem.yml',
33
+ '.gitignore',
34
+ 'CHANGELOG.md',
35
+ 'CITATION.cff',
36
+ 'Gemfile',
37
+ 'LICENSE-0BSD',
38
+ 'README.md',
39
+ 'Rakefile',
40
+ 'ext/z80/extconf.rb',
41
+ 'ext/z80/z80.c',
42
+ 'lib/z80.rb',
43
+ 'lib/z80/version.rb',
44
+ 'z80.gemspec'
45
+ ]
46
+
47
+ s.extensions = %w(ext/z80/extconf.rb)
48
+ s.add_development_dependency 'rake-compiler', '~> 1.2', '>= 1.2.0'
49
+ end
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: z80
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Sainz de Baranda y Goñi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-24 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-01-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.2.0
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.0
13
33
  description: 'Z80-Ruby is a Ruby binding for the Zilog Z80 CPU emulator (https://github.com/redcode/Z80).
14
34
  It is ideal for analysis, hacking, testing and debugging. All from the comfort of
15
35
  Ruby.
@@ -23,8 +43,12 @@ extra_rdoc_files: []
23
43
  files:
24
44
  - ".editorconfig"
25
45
  - ".github/FUNDING.yml"
46
+ - ".github/workflows/build-and-test-extension.yml"
47
+ - ".github/workflows/publish-gem.yml"
26
48
  - ".gitignore"
27
49
  - CHANGELOG.md
50
+ - CITATION.cff
51
+ - Gemfile
28
52
  - LICENSE-0BSD
29
53
  - README.md
30
54
  - Rakefile
@@ -32,15 +56,18 @@ files:
32
56
  - ext/z80/z80.c
33
57
  - lib/z80.rb
34
58
  - lib/z80/version.rb
35
- homepage: https://zxe.io/software/Z80
59
+ - z80.gemspec
60
+ homepage: https://zxe.io/software/Z80-Ruby
36
61
  licenses:
37
62
  - 0BSD
38
63
  metadata:
39
64
  bug_tracker_uri: https://github.com/redcode/Z80-Ruby/issues
40
65
  changelog_uri: https://github.com/redcode/Z80-Ruby/blob/master/CHANGELOG.md
41
- homepage_uri: https://zxe.io/software/Z80
66
+ documentation_uri: https://zxe.io/software/Z80/documentation/latest
67
+ github_repo: ssh://github.com/redcode/Z80-Ruby
68
+ homepage_uri: https://zxe.io/software/Z80-Ruby
42
69
  source_code_uri: https://github.com/redcode/Z80-Ruby
43
- post_install_message:
70
+ post_install_message:
44
71
  rdoc_options: []
45
72
  require_paths:
46
73
  - lib
@@ -55,8 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
82
  - !ruby/object:Gem::Version
56
83
  version: '0'
57
84
  requirements: []
58
- rubygems_version: 3.5.0.dev
59
- signing_key:
85
+ rubygems_version: 3.2.33
86
+ signing_key:
60
87
  specification_version: 4
61
88
  summary: Ruby binding for the Z80 library.
62
89
  test_files: []