z80 0.1.0 → 0.3.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 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: []