nesemul 0.0.1
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 +7 -0
- data/README.md +13 -0
- data/bin/nesemul +50 -0
- data/lib/bitwise.rb +82 -0
- data/lib/cpu.rb +710 -0
- data/lib/opcodes.rb +1 -0
- data/lib/ppu.rb +95 -0
- data/nesemul.gemspec +17 -0
- data/roms/mario.nes +0 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 857b40d37a4f1e744285b7f92eaf7354ae4d35c0
|
4
|
+
data.tar.gz: 50591ad3372d5ee471158dd24f752ca726c7431c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40aec0bf7505fdc6ac8f574ca724de21021fd5229975bfe1022543e42fa6c82c3285e7fb9663cc1d08e0f8c465b59d48a15ab0d10fd726f4e75fb0d4f6a2b67c
|
7
|
+
data.tar.gz: e44c0848ce985ccbd57e947cf0e5a6feec2c6e22f2c19af37ae3dbe6a558f9aa9f2c0d13e8fbd1a884d4c36e352d98179cb4e20f2eb9e2c561dc1797fa52f1ed
|
data/README.md
ADDED
data/bin/nesemul
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
root = File.expand_path("../..", __FILE__)
|
4
|
+
require "sdl"
|
5
|
+
require 'json'
|
6
|
+
require "#{root}/lib/ppu.rb"
|
7
|
+
require "#{root}/lib/cpu.rb"
|
8
|
+
require '#{root}/lib/opcodes.rb'
|
9
|
+
require '#{root}/lib/bitwise.rb'
|
10
|
+
#require '#{root}/OAM.rb'
|
11
|
+
|
12
|
+
|
13
|
+
rom = File.open(ARGV[0]).read.bytes.to_a
|
14
|
+
|
15
|
+
$compteur_cycles = 0
|
16
|
+
$cpu = Cpu.new(rom)
|
17
|
+
$ppu = $cpu.ppu
|
18
|
+
$cpu.reset_rom
|
19
|
+
|
20
|
+
|
21
|
+
def ppu_exec(cycles)
|
22
|
+
(3*cycles).times do
|
23
|
+
$ppu.draw_screen
|
24
|
+
case $compteur_cycles
|
25
|
+
when 0 then $ppu.clear_vblank
|
26
|
+
when 61800
|
27
|
+
$ppu.set_vblank
|
28
|
+
$ppu.screen.flip
|
29
|
+
$cpu.nmi_interrupt if $ppu.registers[0x2000].bit?(7)==1
|
30
|
+
$compteur_cycles = 0
|
31
|
+
end
|
32
|
+
$compteur_cycles += 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
while true
|
37
|
+
nb_args = OPCODES[$cpu.ram[$cpu.cpu[:compteur]]][:len].to_i
|
38
|
+
$cpu.cpu[:compteur_new] += nb_args
|
39
|
+
#puts $cpu.ram.count(nil) if $cpu.ram.count(nil) !=0
|
40
|
+
$cpu.send OPCODES[$cpu.ram[$cpu.cpu[:compteur]]][:opcodes].downcase,
|
41
|
+
$cpu.ram[$cpu.cpu[:compteur]], $cpu.ram[$cpu.cpu[:compteur]+1], $cpu.ram[$cpu.cpu[:compteur]+2]
|
42
|
+
ppu_exec(OPCODES[$cpu.ram[$cpu.cpu[:compteur]]][:tim].to_i)
|
43
|
+
#puts "#{$cpu.ram[$cpu.cpu[:compteur]+1]}, #{$cpu.ram[$cpu.cpu[:compteur]+2]}"
|
44
|
+
#puts "Nom de l'instruct : #{OPCODES[$cpu.ram[$cpu.cpu[:compteur]]][:opcodes]}"
|
45
|
+
#puts "Etat du cpu apres l'instruction #{$cpu.cpu}"
|
46
|
+
#puts "___________________________________________________________________________________________\n"
|
47
|
+
#puts "#{$cpu.cpu[:A]},#{$cpu.ram[52692]},#{$cpu.ram[52692+1]}"
|
48
|
+
$cpu.cpu[:compteur] = $cpu.cpu[:compteur_new]
|
49
|
+
end
|
50
|
+
|
data/lib/bitwise.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
class Integer
|
2
|
+
def int8_plus(integer)
|
3
|
+
((self+integer).abs)%256
|
4
|
+
end
|
5
|
+
|
6
|
+
def int8_minus(integer)
|
7
|
+
if (self-integer)<0
|
8
|
+
(self-integer)+256
|
9
|
+
else
|
10
|
+
(self-integer)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class Fixnum
|
20
|
+
def bit?(bit)
|
21
|
+
if bit == 7
|
22
|
+
value = 0 if self & 128 == 0
|
23
|
+
value = 1 if self & 128 != 0
|
24
|
+
elsif bit == 6
|
25
|
+
value = 0 if self & 64 == 0
|
26
|
+
value = 1 if self & 64 != 0
|
27
|
+
elsif bit == 5
|
28
|
+
value = 0 if self & 32 == 0
|
29
|
+
value = 1 if self & 32 != 0
|
30
|
+
elsif bit == 4
|
31
|
+
value = 0 if self & 16 == 0
|
32
|
+
value = 1 if self & 16 != 0
|
33
|
+
elsif bit == 3
|
34
|
+
value = 0 if self & 8 == 0
|
35
|
+
value = 1 if self & 8 != 0
|
36
|
+
elsif bit == 2
|
37
|
+
value = 0 if self & 4 == 0
|
38
|
+
value = 1 if self & 4 != 0
|
39
|
+
elsif bit == 1
|
40
|
+
value = 0 if self & 2 == 0
|
41
|
+
value = 1 if self & 2 != 0
|
42
|
+
elsif bit == 0
|
43
|
+
value = 0 if self & 1 == 0
|
44
|
+
value = 1 if self & 1 != 0
|
45
|
+
end
|
46
|
+
|
47
|
+
return value
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_bit(bit)
|
51
|
+
self | case bit
|
52
|
+
when 7 then 128
|
53
|
+
when 6 then 64
|
54
|
+
when 5 then 32
|
55
|
+
when 4 then 16
|
56
|
+
when 3 then 8
|
57
|
+
when 2 then 4
|
58
|
+
when 1 then 2
|
59
|
+
when 0 then 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def clear_bit(bit)
|
64
|
+
self & case bit
|
65
|
+
when 7 then 127
|
66
|
+
when 6 then 191
|
67
|
+
when 5 then 223
|
68
|
+
when 4 then 239
|
69
|
+
when 3 then 247
|
70
|
+
when 2 then 251
|
71
|
+
when 1 then 253
|
72
|
+
when 0 then 254
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def signed(int)
|
79
|
+
table_conversion = Array(0..128) + Array(-127..-1)
|
80
|
+
return table_conversion[int]
|
81
|
+
end
|
82
|
+
|
data/lib/cpu.rb
ADDED
@@ -0,0 +1,710 @@
|
|
1
|
+
class Cpu
|
2
|
+
attr_accessor :ram
|
3
|
+
attr_accessor :cpu
|
4
|
+
attr_accessor :ppu
|
5
|
+
|
6
|
+
def initialize(rom)
|
7
|
+
@ram = [0]*100000
|
8
|
+
@ppu = Ppu.new
|
9
|
+
#@oam = Oam.new
|
10
|
+
prg_start_index = map_rom(rom)
|
11
|
+
@cpu = {:Y=>0,:X=>0,:A=>0,:S=>255,:P=>0,:compteur=>prg_start_index,:compteur_new=>prg_start_index}
|
12
|
+
end
|
13
|
+
|
14
|
+
def map_rom(rom)
|
15
|
+
header = rom.shift(16)
|
16
|
+
if header[4] == 1
|
17
|
+
prg_start_index = 0xC000 #Index de mappage de la PRG (- de 16Ko de PRG)
|
18
|
+
else
|
19
|
+
prg_start_index = 0x8000 #Index de mappage de la PRG (+ de 16Ko de PRG)
|
20
|
+
end
|
21
|
+
if header[6].bit?(2) == 1
|
22
|
+
trainer = rom.shift(512)
|
23
|
+
@ram[0x7000,trainer.length] = trainer # Mapping du trainer dans la RAM
|
24
|
+
end
|
25
|
+
prg_rom = rom.shift(header[4]*16384)
|
26
|
+
chr_rom = rom.shift(header[5]*8192)
|
27
|
+
@ppu.ppu[0,chr_rom.length] = chr_rom
|
28
|
+
@ram[prg_start_index,prg_rom.length] = prg_rom # Mapping de la PRG dans la RAM
|
29
|
+
return prg_start_index
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def nmi_interrupt()
|
34
|
+
bytefort = @cpu[:compteur_new] >> 8
|
35
|
+
bytefaible = @cpu[:compteur_new] & 0x00FF
|
36
|
+
@ram[@cpu[:S]+0x100] = bytefort # octet de poids fort
|
37
|
+
@cpu[:S] -= 1 #decrementation pour la prochaine valeur
|
38
|
+
@ram[@cpu[:S]+0x100] = bytefaible #octet de poids faible
|
39
|
+
@cpu[:S] -= 1
|
40
|
+
@ram[@cpu[:S]+0x100] = @cpu[:P] #status
|
41
|
+
@cpu[:S] -= 1
|
42
|
+
@cpu[:compteur_new] = read(0xFFFA)+(read(0xFFFB)*256)
|
43
|
+
@cpu[:P] = @cpu[:P].set_bit(2)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
def reset_rom()
|
49
|
+
reset_address = @ram[0xFFFC]+(@ram[0xFFFD]*256)
|
50
|
+
@cpu[:compteur] = @cpu[:compteur_new] = reset_address
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def cmp(zone,arg1,arg2)
|
55
|
+
opcode = zone.to_s(16).upcase
|
56
|
+
sign_zero_carry @cpu[:A].int8_minus signed case opcode
|
57
|
+
when "C9" then arg1
|
58
|
+
when "C5" then read(arg1)
|
59
|
+
when "D5" then read(arg1+@cpu[:X])
|
60
|
+
when "CD" then read(arg1+(arg2*256))
|
61
|
+
when "DD" then read(arg1+(arg2*256)+@cpu[:X])
|
62
|
+
when "D9" then read(arg1+(arg2*256)+@cpu[:Y])
|
63
|
+
when "C1" then read(read(arg1+@cpu[:X]) + (read(arg1+@cpu[:X]+1)*256))
|
64
|
+
when "D1" then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def asl(zone,arg1,arg2)
|
69
|
+
opcode = zone.to_s(16).upcase
|
70
|
+
sign_zero_set_switch case zone
|
71
|
+
when 0x0A then @cpu[:A] << 1
|
72
|
+
when 0x06 then write(arg1,read(arg1) << 1)
|
73
|
+
when 0x16 then write(arg1+@cpu[:X], read(arg1+@cpu[:X]) << 1)
|
74
|
+
when 0x0E then write(arg1+(arg2*256),read(arg1+(arg2*256)) << 1)
|
75
|
+
when 0x1E then write(arg1+(arg2*256)+@cpu[:X],read(arg1+(arg2*256)+@cpu[:X]) << 1)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def rol(zone,arg1,arg2)
|
80
|
+
opcode = zone.to_s(16).upcase
|
81
|
+
sign_zero_set case opcode
|
82
|
+
when "2A" then @cpu[:A] = rotate_left(@cpu[:A])
|
83
|
+
when "26" then write(arg1,rotate_left(read(arg1)))
|
84
|
+
when "36" then write(arg1+@cpu[:X], rotate_left(read(arg1+@cpu[:X])))
|
85
|
+
when "2E" then write(arg1+(arg2*256), rotate_left(read(arg1+(arg2*256))))
|
86
|
+
when "3E" then write(arg1+(arg2*256)+@cpu[:X], rotate_left(read(arg1+(arg2*256)+@cpu[:X])))
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def ror(zone,arg1,arg2)
|
92
|
+
opcode = zone.to_s(16).upcase
|
93
|
+
sign_zero_set case opcode
|
94
|
+
when "6A" then @cpu[:A] = rotate_right(@cpu[:A])
|
95
|
+
when "66" then write(arg1,rotate_right(read(arg1)))
|
96
|
+
when "76" then write(arg1+@cpu[:X], rotate_right(read(arg1+@cpu[:X])))
|
97
|
+
when "6E" then write(arg1+(arg2*256), rotate_right(read(arg1+(arg2*256))))
|
98
|
+
when "7E" then write(arg1+(arg2*256)+@cpu[:X], rotate_right(read(arg1+(arg2*256)+@cpu[:X])))
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def rotate_left(byte)
|
104
|
+
byte.bit?(7) == 1 ? @cpu[:P] = @cpu[:P].set_bit(0) : @cpu[:P] = @cpu[:P].clear_bit(0)
|
105
|
+
@cpu[:P].bit?(0) == 1 ? byte = ((byte << 1)&0xFF)| 1 : byte = ((byte << 1)&0xFF)| 0
|
106
|
+
@cpu[:P] = @cpu[:P].clear_bit(0) if byte.bit?(7) == 0 #clear carry
|
107
|
+
@cpu[:P] = @cpu[:P].set_bit(0) if byte.bit?(7) == 1 #set carry
|
108
|
+
return byte
|
109
|
+
end
|
110
|
+
|
111
|
+
def rotate_right(byte)
|
112
|
+
byte.bit?(0) == 1 ? @cpu[:P] = @cpu[:P].set_bit(0) : @cpu[:P] = @cpu[:P].clear_bit(0)
|
113
|
+
@cpu[:P].bit?(0) ==1 ? byte = (byte >> 1)| 128 : byte = (byte >> 1)| 0
|
114
|
+
@cpu[:P] = @cpu[:P].clear_bit(0) if byte.bit?(0) == 0 #clear carry
|
115
|
+
@cpu[:P] = @cpu[:P].set_bit(0) if byte.bit?(0)==1 #set carry
|
116
|
+
return byte
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
def lsr(zone,arg1,arg2)
|
122
|
+
opcode = zone.to_s(16).upcase
|
123
|
+
sign_zero_set_switch case opcode
|
124
|
+
when "4A" then @cpu[:A] = @cpu[:A] >> 1
|
125
|
+
when "46" then write(arg1,read(arg1) >> 1)
|
126
|
+
when "56" then write(arg1+@cpu[:X], read(arg1+@cpu[:X]) >> 1)
|
127
|
+
when "4E" then write(arg1+(arg2*256),read(arg1+(arg2*256)) >> 1)
|
128
|
+
when "5E" then write(arg1+(arg2*256)+@cpu[:X], read(arg1+(arg2*256)+@cpu[:X]) >> 1)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
def cpx(zone,arg1,arg2)
|
136
|
+
opcode = zone.to_s(16).upcase
|
137
|
+
sign_zero_carry @cpu[:X].int8_minus signed case opcode
|
138
|
+
when "E0" then arg1
|
139
|
+
when "E4" then read(arg1)
|
140
|
+
when "EC" then read(arg1+(arg2*256))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def cpy(zone,arg1,arg2)
|
145
|
+
opcode = zone.to_s(16).upcase
|
146
|
+
sign_zero_carry @cpu[:Y].int8_minus signed case opcode
|
147
|
+
when "C0" then arg1
|
148
|
+
when "C4" then read(arg1)
|
149
|
+
when "CC" then read(arg1+(arg2*256))
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def and(zone,arg1,arg2)
|
156
|
+
opcode = zone.to_s(16).upcase
|
157
|
+
@cpu[:A] = @cpu[:A] & case opcode
|
158
|
+
when "29" then arg1
|
159
|
+
when "25" then read(arg1)
|
160
|
+
when "35" then read(arg1+@cpu[:X])
|
161
|
+
when "2D" then read(arg1+(arg2*256))
|
162
|
+
when "3D" then read(arg1+(arg2*256)+@cpu[:X])
|
163
|
+
when "39" then read(arg1+(arg2*256)+@cpu[:Y])
|
164
|
+
when "21" then read(read(arg1+@cpu[:X]) + read(arg1+@cpu[:X]+1)*256)
|
165
|
+
when "31" then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y])
|
166
|
+
end
|
167
|
+
sign_zero_set(@cpu[:A])
|
168
|
+
end
|
169
|
+
|
170
|
+
def eor(zone,arg1,arg2)
|
171
|
+
opcode = zone.to_s(16).upcase
|
172
|
+
@cpu[:A] = @cpu[:A] ^ case opcode
|
173
|
+
when "49" then arg1
|
174
|
+
when "45" then read(arg1)
|
175
|
+
when "55" then read(arg1+@cpu[:X])
|
176
|
+
when "4D" then read(arg1+(arg2*256))
|
177
|
+
when "5D" then read(arg1+(arg2*256)+@cpu[:X])
|
178
|
+
when "59" then read(arg1+(arg2*256)+@cpu[:Y])
|
179
|
+
when "41" then read(read(arg1+@cpu[:X]) + read(arg1+@cpu[:X]+1)*256)
|
180
|
+
when "51" then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y])
|
181
|
+
end
|
182
|
+
sign_zero_set(@cpu[:A])
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def ora(zone,arg1,arg2)
|
187
|
+
@cpu[:A] |= case zone
|
188
|
+
when 0x09 then arg1
|
189
|
+
when 0x05 then read(arg1)
|
190
|
+
when 0x15 then read(arg1+@cpu[:X])
|
191
|
+
when 0x0D then read(arg1+(arg2*256))
|
192
|
+
when 0x1D then read(arg1+(arg2*256)+@cpu[:X])
|
193
|
+
when 0x19 then read(arg1+(arg2*256)+@cpu[:Y])
|
194
|
+
when 0x01 then read(read(arg1+@cpu[:X]) + read(arg1+@cpu[:X]+1)*256)
|
195
|
+
when 0x11 then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y])
|
196
|
+
end
|
197
|
+
sign_zero_set(@cpu[:A])
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
def clc(x,y,z)
|
202
|
+
@cpu[:P] = @cpu[:P].clear_bit(0)
|
203
|
+
end
|
204
|
+
|
205
|
+
def sec(x,y,z)
|
206
|
+
@cpu[:P] = @cpu[:P].set_bit(0)
|
207
|
+
end
|
208
|
+
|
209
|
+
def cli(x,y,z)
|
210
|
+
@cpu[:P] = @cpu[:P].clear_bit(2)
|
211
|
+
end
|
212
|
+
|
213
|
+
def sei(x,y,z)
|
214
|
+
@cpu[:P] = @cpu[:P].set_bit(2)
|
215
|
+
end
|
216
|
+
|
217
|
+
def clv(x,y,z)
|
218
|
+
@cpu[:P] = @cpu[:P].clear_bit(6)
|
219
|
+
end
|
220
|
+
|
221
|
+
def cld(x,y,z)
|
222
|
+
@cpu[:P] = @cpu[:P].clear_bit(3)
|
223
|
+
end
|
224
|
+
|
225
|
+
def sed(x,y,z)
|
226
|
+
@cpu[:P] = @cpu[:P].set_bit(3)
|
227
|
+
end
|
228
|
+
|
229
|
+
def nop(x,y,z)
|
230
|
+
end
|
231
|
+
|
232
|
+
def bit(zone,arg1,arg2)
|
233
|
+
opcode = zone.to_s(16).upcase
|
234
|
+
case opcode
|
235
|
+
when "24"
|
236
|
+
valeur = read(arg1)
|
237
|
+
if valeur.bit?(7) == 0
|
238
|
+
@cpu[:P] = @cpu[:P].clear_bit(7) #clear
|
239
|
+
else
|
240
|
+
@cpu[:P] = @cpu[:P].set_bit(7) #set
|
241
|
+
end
|
242
|
+
if valeur.bit?(6) == 0
|
243
|
+
@cpu[:P] = @cpu[:P].clear_bit(6) #clear
|
244
|
+
else
|
245
|
+
@cpu[:P] = @cpu[:P].set_bit(6) #set
|
246
|
+
end
|
247
|
+
if valeur & @cpu[:A] == 0
|
248
|
+
@cpu[:P] = @cpu[:P].set_bit(1) #set
|
249
|
+
else
|
250
|
+
@cpu[:P] = @cpu[:P].clear_bit(1) #clear
|
251
|
+
end
|
252
|
+
when "2C"
|
253
|
+
valeur = read(arg1+(arg2*256))
|
254
|
+
if valeur.bit?(7) == 0
|
255
|
+
@cpu[:P] = @cpu[:P].clear_bit(7) #clear
|
256
|
+
else
|
257
|
+
@cpu[:P] = @cpu[:P].set_bit(7) #set
|
258
|
+
end
|
259
|
+
if valeur.bit?(6) == 0
|
260
|
+
@cpu[:P] = @cpu[:P].clear_bit(6) #clear
|
261
|
+
else
|
262
|
+
@cpu[:P] = @cpu[:P].set_bit(6) #set
|
263
|
+
end
|
264
|
+
if valeur & @cpu[:A] == 0
|
265
|
+
@cpu[:P] = @cpu[:P].set_bit(1) #set
|
266
|
+
else
|
267
|
+
@cpu[:P] = @cpu[:P].clear_bit(1) #clear
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
###Rappel : dans 0xC0E1 , C0 est l'octet de poids fort et E1 celui de poids faible
|
274
|
+
|
275
|
+
def jsr(zone,arg1,arg2)
|
276
|
+
adresse = @cpu[:compteur_new] -1
|
277
|
+
bytefort = adresse >> 8 #byte fort
|
278
|
+
bytefaible = adresse & 0x00FF #byte faible
|
279
|
+
@ram[@cpu[:S]+0x100] = bytefort # adresse actuelle
|
280
|
+
@cpu[:S] -= 1 #decrementation pour la prochaine valeur
|
281
|
+
@ram[@cpu[:S]+0x100] = bytefaible
|
282
|
+
@cpu[:S] -= 1
|
283
|
+
@cpu[:compteur_new] = arg1+(arg2*256)
|
284
|
+
end
|
285
|
+
|
286
|
+
def rts(zone,arg1,arg2)
|
287
|
+
bytefaible = @ram[@cpu[:S]+1+0x100]
|
288
|
+
bytefort = @ram[@cpu[:S]+2+0x100]
|
289
|
+
@cpu[:compteur_new] = bytefaible+(bytefort*256) +1
|
290
|
+
@cpu[:S]+=2 # pour ecraser l'adresse précédente sur 2x8bits
|
291
|
+
end
|
292
|
+
|
293
|
+
def rti(zone,arg1,arg2)
|
294
|
+
bytefort = @ram[@cpu[:S]+3+0x100]
|
295
|
+
bytefaible = @ram[@cpu[:S]+2+0x100]
|
296
|
+
status = @ram[@cpu[:S]+1+0x100]
|
297
|
+
@cpu[:compteur_new] = bytefaible+(bytefort*256)
|
298
|
+
@cpu[:P] = status #récup du status
|
299
|
+
@cpu[:S]+=3 # pour ecraser l'adresse précédente sur 3x8bits
|
300
|
+
end
|
301
|
+
|
302
|
+
def brk(x,y,z)
|
303
|
+
#Interruption push d'abord l'octet de poids fort ensuite octet de pds faible ensuite le status
|
304
|
+
bytefort = @cpu[:compteur_new] >> 8
|
305
|
+
bytefaible = @cpu[:compteur_new] & 0x00FF
|
306
|
+
@ram[@cpu[:S]+0x100] = bytefort # octet de poids fort
|
307
|
+
@cpu[:S] -= 1 #decrementation pour la prochaine valeur
|
308
|
+
@ram[@cpu[:S]+0x100] = bytefaible #octet de poids faible
|
309
|
+
@cpu[:S] -= 1
|
310
|
+
@ram[@cpu[:S]+0x100] = @cpu[:P] #status
|
311
|
+
@cpu[:S] -= 1
|
312
|
+
@cpu[:compteur_new] = read(0xFFFE)+(read(0xFFFF)*256)
|
313
|
+
@cpu[:P] = @cpu[:P].set_bit(4)
|
314
|
+
end
|
315
|
+
|
316
|
+
def php(x,y,z)
|
317
|
+
end
|
318
|
+
|
319
|
+
def jmp(zone,arg1,arg2)
|
320
|
+
opcode = zone.to_s(16).upcase
|
321
|
+
@cpu[:compteur_new] = case opcode
|
322
|
+
when "4C" then arg1+(arg2*256)
|
323
|
+
when "6C" then read(arg1+(arg2*256))+(read(arg1+(arg2*256)+1)*256)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def adc(zone,arg1,arg2)
|
328
|
+
opcode = zone.to_s(16).upcase
|
329
|
+
accumulator_temp = @cpu[:A]
|
330
|
+
@cpu[:P].bit?(0) == 1 ? valeur_carry = 1 : valeur_carry = 0
|
331
|
+
@cpu[:A] = @cpu[:A].int8_plus case opcode
|
332
|
+
when "69" then arg1.int8_plus(valeur_carry)
|
333
|
+
when "65" then read(arg1).int8_plus(valeur_carry)
|
334
|
+
when "75" then read(arg1+@cpu[:X]).int8_plus(valeur_carry)
|
335
|
+
when "6D" then read(arg1+(arg2*256)).int8_plus(valeur_carry)
|
336
|
+
when "7D" then read(arg1+(arg2*256)+@cpu[:X]).int8_plus(valeur_carry)
|
337
|
+
when "79" then read(arg1+(arg2*256)+@cpu[:Y]).int8_plus(valeur_carry)
|
338
|
+
when "61" then read(read(arg1+@cpu[:X]) + (read(arg1+@cpu[:X]+1)*256)).int8_plus(valeur_carry)
|
339
|
+
when "71" then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y]).int8_plus(valeur_carry)
|
340
|
+
end
|
341
|
+
@cpu[:P] = @cpu[:P].clear_bit(0) #clear the carry
|
342
|
+
set_overflow(accumulator_temp)
|
343
|
+
sign_zero_clear_or_set(@cpu[:A])
|
344
|
+
end
|
345
|
+
|
346
|
+
def sbc(zone,arg1,arg2)
|
347
|
+
opcode = zone.to_s(16).upcase
|
348
|
+
accumulator_temp = @cpu[:A]
|
349
|
+
@cpu[:P].bit?(0) == 1 ? valeur_carry = 1 : valeur_carry = 0
|
350
|
+
@cpu[:A] = @cpu[:A].int8_minus case opcode
|
351
|
+
when "E9" then arg1.int8_minus(valeur_carry)
|
352
|
+
when "E5" then read(arg1).int8_minus(valeur_carry)
|
353
|
+
when "F5" then read(arg1+@cpu[:X]).int8_minus(valeur_carry)
|
354
|
+
when "ED" then read(arg1+(arg2*256)).int8_minus(valeur_carry)
|
355
|
+
when "FD" then read(arg1+(arg2*256)+@cpu[:X]).int8_minus(valeur_carry)
|
356
|
+
when "F9" then read(arg1+(arg2*256)+@cpu[:Y]).int8_minus(valeur_carry)
|
357
|
+
when "E1" then read(read(arg1+@cpu[:X]) + (read(arg1+@cpu[:X]+1)*256)).int8_minus(valeur_carry)
|
358
|
+
when "F1" then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y]).int8_minus(valeur_carry)
|
359
|
+
end
|
360
|
+
@cpu[:P] = @cpu[:P].set_bit(0) #set the carry
|
361
|
+
set_overflow(accumulator_temp)
|
362
|
+
sign_zero_clear_or_set(@cpu[:A])
|
363
|
+
end
|
364
|
+
|
365
|
+
def dec(zone,arg1,arg2)
|
366
|
+
opcode = zone.to_s(16).upcase
|
367
|
+
sign_zero_clear_or_set case opcode
|
368
|
+
when "C6" then write(arg1,read(arg1).int8_minus(1))
|
369
|
+
when "D6" then write(arg1+@cpu[:X],read(arg1+@cpu[:X]).int8_minus(1))
|
370
|
+
when "CE" then write(arg1+(arg2*256),read(arg1+(arg2*256)).int8_minus(1))
|
371
|
+
when "DE" then write(arg1+(arg2*256)+@cpu[:X],read(arg1+(arg2*256)+@cpu[:X]).int8_minus(1))
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def inc(zone,arg1,arg2)
|
376
|
+
opcode = zone.to_s(16).upcase
|
377
|
+
sign_zero_clear_or_set case opcode
|
378
|
+
when "E6" then write(arg1,read(arg1).int8_plus(1))
|
379
|
+
when "F6" then write(arg1+@cpu[:X],read(arg1+@cpu[:X]).int8_plus(1))
|
380
|
+
when "EE" then write(arg1+(arg2*256),read(arg1+(arg2*256)).int8_plus(1))
|
381
|
+
when "FE" then write(arg1+(arg2*256)+@cpu[:X],read(arg1+(arg2*256)+@cpu[:X]).int8_plus(1))
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def lda(zone,arg1,arg2)
|
386
|
+
opcode = zone.to_s(16).upcase
|
387
|
+
@cpu[:A] = case opcode
|
388
|
+
when "A9" then arg1
|
389
|
+
when "A5" then read(arg1)
|
390
|
+
when "B5" then read(arg1+@cpu[:X])
|
391
|
+
when "AD" then read(arg1+(arg2*256))
|
392
|
+
when "BD" then read(arg1+(arg2*256)+@cpu[:X])
|
393
|
+
when "B9" then read(arg1+(arg2*256)+@cpu[:Y])
|
394
|
+
when "A1" then read(read(arg1+@cpu[:X]) + (read(arg1+@cpu[:X]+1)*256))
|
395
|
+
when "B1" then read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y])
|
396
|
+
end
|
397
|
+
sign_zero_set(@cpu[:A])
|
398
|
+
end
|
399
|
+
|
400
|
+
def ldx(zone,arg1,arg2)
|
401
|
+
opcode = zone.to_s(16).upcase
|
402
|
+
@cpu[:X] = case opcode
|
403
|
+
when "A2" then arg1
|
404
|
+
when "A6" then read(arg1)
|
405
|
+
when "B6" then read(arg1+@cpu[:Y])
|
406
|
+
when "AE" then read(arg1+(arg2*256))
|
407
|
+
when "BE" then read(arg1+(arg2*256)+@cpu[:Y])
|
408
|
+
end
|
409
|
+
sign_zero_set(@cpu[:X])
|
410
|
+
end
|
411
|
+
|
412
|
+
def ldy(zone,arg1,arg2)
|
413
|
+
opcode = zone.to_s(16).upcase
|
414
|
+
@cpu[:Y] = case opcode
|
415
|
+
when "A0" then arg1
|
416
|
+
when "A4" then read(arg1)
|
417
|
+
when "B4" then read(arg1+@cpu[:X])
|
418
|
+
when "AC" then read(arg1+(arg2*256))
|
419
|
+
when "BC" then read(arg1+(arg2*256)+@cpu[:X])
|
420
|
+
end
|
421
|
+
sign_zero_set(@cpu[:Y])
|
422
|
+
end
|
423
|
+
|
424
|
+
|
425
|
+
def sta(zone,arg1,arg2)
|
426
|
+
opcode = zone.to_s(16).upcase
|
427
|
+
case opcode
|
428
|
+
when "85" then write(arg1,@cpu[:A])
|
429
|
+
when "95" then write(arg1+@cpu[:X],@cpu[:A])
|
430
|
+
when "8D" then write(arg1+(arg2*256),@cpu[:A])
|
431
|
+
when "9D" then write(arg1+(arg2*256)+@cpu[:X], @cpu[:A])
|
432
|
+
when "99" then write(arg1+(arg2*256)+@cpu[:Y], @cpu[:A])
|
433
|
+
when "81" then write(read(read(arg1+@cpu[:X]) + (read(arg1+@cpu[:X]+1)*256)),@cpu[:A])
|
434
|
+
when "91" then write(read(read(arg1)+(read(arg1+1)*256)+@cpu[:Y]), @cpu[:A])
|
435
|
+
end
|
436
|
+
sign_zero_set(@cpu[:A])
|
437
|
+
end
|
438
|
+
|
439
|
+
def stx(zone,arg1,arg2)
|
440
|
+
opcode = zone.to_s(16).upcase
|
441
|
+
case opcode
|
442
|
+
when "86" then write(arg1, @cpu[:X])
|
443
|
+
when "96" then write(arg1+@cpu[:Y], @cpu[:X])
|
444
|
+
when "8E" then write(arg1+(arg2*256),@cpu[:X])
|
445
|
+
end
|
446
|
+
sign_zero_set(@cpu[:X])
|
447
|
+
end
|
448
|
+
|
449
|
+
def sty(zone,arg1,arg2)
|
450
|
+
opcode = zone.to_s(16).upcase
|
451
|
+
case opcode
|
452
|
+
when "84" then write(arg1, @cpu[:Y])
|
453
|
+
when "94" then write(arg1+@cpu[:X], @cpu[:Y])
|
454
|
+
when "8C" then write(arg1+(arg2*256),@cpu[:Y])
|
455
|
+
end
|
456
|
+
sign_zero_set(@cpu[:Y])
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
|
461
|
+
def tax(x,y,z)
|
462
|
+
@cpu[:X] = @cpu[:A]
|
463
|
+
sign_zero_set(@cpu[:X])
|
464
|
+
end
|
465
|
+
|
466
|
+
def txa(x,y,z)
|
467
|
+
@cpu[:A] = @cpu[:X]
|
468
|
+
sign_zero_set(@cpu[:A])
|
469
|
+
end
|
470
|
+
|
471
|
+
def dex(x,y,z)
|
472
|
+
@cpu[:X] = @cpu[:X].int8_minus(1)
|
473
|
+
sign_zero_clear_or_set(@cpu[:X])
|
474
|
+
end
|
475
|
+
|
476
|
+
def inx(x,y,z)
|
477
|
+
@cpu[:X] = @cpu[:X].int8_plus(1)
|
478
|
+
sign_zero_clear_or_set(@cpu[:X])
|
479
|
+
end
|
480
|
+
|
481
|
+
def tay(x,y,z)
|
482
|
+
@cpu[:Y] = @cpu[:A]
|
483
|
+
sign_zero_set(@cpu[:Y])
|
484
|
+
end
|
485
|
+
|
486
|
+
def tya(x,y,z)
|
487
|
+
@cpu[:A] = @cpu[:Y]
|
488
|
+
sign_zero_set(@cpu[:A])
|
489
|
+
end
|
490
|
+
|
491
|
+
def dey(x,y,z)
|
492
|
+
@cpu[:Y] = @cpu[:Y].int8_minus(1)
|
493
|
+
sign_zero_clear_or_set(@cpu[:Y])
|
494
|
+
end
|
495
|
+
|
496
|
+
def iny(x,y,z)
|
497
|
+
@cpu[:Y] = @cpu[:Y].int8_plus(1)
|
498
|
+
sign_zero_clear_or_set(@cpu[:Y])
|
499
|
+
end
|
500
|
+
|
501
|
+
def txs(x,y,z)
|
502
|
+
@cpu[:S] = @cpu[:X]
|
503
|
+
end
|
504
|
+
|
505
|
+
def tsx(x,y,z)
|
506
|
+
@cpu[:X] = @cpu[:S]
|
507
|
+
end
|
508
|
+
|
509
|
+
def pha(x,y,z)
|
510
|
+
@ram[@cpu[:S]+0x100] = @cpu[:A]
|
511
|
+
@cpu[:S] -= 1
|
512
|
+
end
|
513
|
+
|
514
|
+
def pla(x,y,z)
|
515
|
+
@cpu[:A] = @ram[@cpu[:S]+1+0x100] #dernier elem
|
516
|
+
@cpu[:S] += 1
|
517
|
+
end
|
518
|
+
|
519
|
+
def php(x,y,z)
|
520
|
+
@ram[@cpu[:S]+0x100] = @cpu[:P]
|
521
|
+
@cpu[:S] -= 1
|
522
|
+
end
|
523
|
+
|
524
|
+
def plp(x,y,z)
|
525
|
+
@cpu[:A] = @ram[@cpu[:S]+1+0x100]
|
526
|
+
@cpu[:S] += 1
|
527
|
+
|
528
|
+
end
|
529
|
+
|
530
|
+
def bcc(zone,arg1,arg2)
|
531
|
+
if @cpu[:P].bit?(0) == 0
|
532
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
def bcs(zone,arg1,arg2)
|
537
|
+
if @cpu[:P].bit?(0) == 1
|
538
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
def bvc(zone,arg1,arg2)
|
543
|
+
if @cpu[:P].bit?(6) == 0
|
544
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
def bvs(zone,arg1,arg2)
|
549
|
+
if @cpu[:P].bit?(6) == 1
|
550
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
def bpl(zone,arg1,arg2)
|
555
|
+
if @cpu[:P].bit?(7) == 0
|
556
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def bmi(zone,arg1,arg2)
|
561
|
+
if @cpu[:P].bit?(7) == 1
|
562
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
def bne(zone,arg1,arg2)
|
567
|
+
if @cpu[:P].bit?(1) == 0
|
568
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
def beq(zone,arg1,arg2)
|
573
|
+
if @cpu[:P].bit?(1) == 1
|
574
|
+
@cpu[:compteur_new] = @cpu[:compteur_new]+signed(arg1)
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
|
579
|
+
def set_overflow(byte)
|
580
|
+
if @cpu[:A].bit?(6) != byte.bit?(6)
|
581
|
+
@cpu[:P] = @cpu[:P].set_bit(6)
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
|
586
|
+
def sign_zero_carry(byte)
|
587
|
+
if byte & 0x80 == 0
|
588
|
+
@cpu[:P] = @cpu[:P].set_bit(0)
|
589
|
+
@cpu[:P] = @cpu[:P].clear_bit(7)
|
590
|
+
@cpu[:P] = @cpu[:P].clear_bit(1)
|
591
|
+
elsif byte == 0
|
592
|
+
@cpu[:P] = @cpu[:P].set_bit(0)
|
593
|
+
@cpu[:P] = @cpu[:P].clear_bit(7)
|
594
|
+
@cpu[:P] = @cpu[:P].set_bit(1)
|
595
|
+
elsif byte & 0x80 != 0
|
596
|
+
@cpu[:P] = @cpu[:P].clear_bit(0)
|
597
|
+
@cpu[:P] = @cpu[:P].set_bit(7)
|
598
|
+
@cpu[:P] = @cpu[:P].clear_bit(1)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
def sign_zero_clear_or_set(byte) #Clears or sets flag
|
603
|
+
if byte==0
|
604
|
+
@cpu[:P] = @cpu[:P].set_bit(1)
|
605
|
+
else
|
606
|
+
@cpu[:P] = @cpu[:P].clear_bit(1)
|
607
|
+
end
|
608
|
+
|
609
|
+
if byte & 0x80 == 0
|
610
|
+
@cpu[:P] = @cpu[:P].clear_bit(7)
|
611
|
+
else
|
612
|
+
@cpu[:P] = @cpu[:P].set_bit(7)
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
def sign_zero_set(byte) #Only sets flag ( in case of load or store instruction )
|
617
|
+
if byte==0
|
618
|
+
@cpu[:P] = @cpu[:P].set_bit(1)
|
619
|
+
else
|
620
|
+
@cpu[:P] = @cpu[:P].clear_bit(1)
|
621
|
+
end
|
622
|
+
|
623
|
+
if byte & 0x80 != 0
|
624
|
+
@cpu[:P] = @cpu[:P].set_bit(7)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
def sign_zero_set_switch(byte) # S_z_set, mais avec le petit bonus "Carry" pour les opcodes de switch !
|
629
|
+
if byte==0
|
630
|
+
@cpu[:P] = @cpu[:P].set_bit(1)
|
631
|
+
end
|
632
|
+
if byte & 0x80 != 0
|
633
|
+
@cpu[:P] = @cpu[:P].set_bit(7)
|
634
|
+
@cpu[:P] = @cpu[:P].set_bit(0) #set carry
|
635
|
+
end
|
636
|
+
@cpu[:P] = @cpu[:P].clear_bit(0) if byte & 0x80 == 0 #clear carry
|
637
|
+
end
|
638
|
+
|
639
|
+
|
640
|
+
|
641
|
+
|
642
|
+
|
643
|
+
|
644
|
+
|
645
|
+
def read(adresse)
|
646
|
+
|
647
|
+
case adresse
|
648
|
+
when 0x2007
|
649
|
+
@ppu.registers[0x2000].bit?(2) ==1 ? @pointeur_2006+=32 : @pointeur_2006+=1
|
650
|
+
|
651
|
+
|
652
|
+
when 0x2004
|
653
|
+
@ppu.registers[0x2003] = @ppu.registers[0x2003].int8_plus(1)
|
654
|
+
end
|
655
|
+
|
656
|
+
if Registers.include?(adresse)
|
657
|
+
return @ppu.registers[adresse]
|
658
|
+
else
|
659
|
+
return @ram[adresse]
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
|
664
|
+
|
665
|
+
def write(adresse,value)
|
666
|
+
|
667
|
+
case adresse
|
668
|
+
when 0x2007
|
669
|
+
print value
|
670
|
+
@ppu.ppu[@pointeur_2006] = value
|
671
|
+
|
672
|
+
@ppu.registers[0x2000].bit?(2) ==1 ? @pointeur_2006+=32 : @pointeur_2006+=1
|
673
|
+
|
674
|
+
when 0x2006
|
675
|
+
if @pointeur_2006==nil
|
676
|
+
@pointeur_2006 = value
|
677
|
+
elsif @pointeur_2006 <= 0xFF
|
678
|
+
@pointeur_2006 = value + (@pointeur_2006 *256) ###CA VIENDRAIT DE Là
|
679
|
+
elsif @pointeur_2006 > 0xFF
|
680
|
+
@pointeur_2006 = value
|
681
|
+
end
|
682
|
+
until @pointeur_2006.between?(0,0x3FFF)
|
683
|
+
@pointeur_2006 -= 0x4000
|
684
|
+
end
|
685
|
+
|
686
|
+
|
687
|
+
when 0x2004
|
688
|
+
@OAM[@ppu.registers[0x2003]] = value
|
689
|
+
@ppu.registers[0x2003] = @ppu.registers[0x2003].int8_plus(1)
|
690
|
+
|
691
|
+
when 0x4014
|
692
|
+
@OAM = @ram[value*0x100..(value*0x100)+0xFF]
|
693
|
+
end
|
694
|
+
|
695
|
+
if Registers.include?(adresse)
|
696
|
+
@ppu.registers[adresse] = value
|
697
|
+
return @ppu.registers[adresse]
|
698
|
+
else
|
699
|
+
@ram[adresse] = value
|
700
|
+
return @ram[adresse]
|
701
|
+
end
|
702
|
+
|
703
|
+
end
|
704
|
+
|
705
|
+
|
706
|
+
end
|
707
|
+
|
708
|
+
|
709
|
+
|
710
|
+
#attr_accessor #googler ça
|
data/lib/opcodes.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
OPCODES =[{:hex=>"00", :opcodes=>"BRK", :mode=>"", :len=>"1", :tim=>"7"}, {:hex=>"01", :opcodes=>"ORA", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"02", :opcodes=>"", :mode=>""}, {:hex=>"03", :opcodes=>"", :mode=>""}, {:hex=>"04", :opcodes=>"", :mode=>""}, {:hex=>"05", :opcodes=>"ORA", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"06", :opcodes=>"ASL", :mode=>"Zero Page", :len=>"2", :tim=>"5"}, {:hex=>"07", :opcodes=>"", :mode=>""}, {:hex=>"08", :len=>"1", :opcodes=>"PHP", :mode=>"", :tim=>"3"}, {:hex=>"09", :opcodes=>"ORA", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"0A", :opcodes=>"ASL", :mode=>"Accumulator", :len=>"1", :tim=>"2"}, {:hex=>"0B", :opcodes=>"", :mode=>""}, {:hex=>"0C", :opcodes=>"", :mode=>""}, {:hex=>"0D", :opcodes=>"ORA", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"0E", :opcodes=>"ASL", :mode=>"Absolute", :len=>"3", :tim=>"6"}, {:hex=>"0F", :opcodes=>"", :mode=>""}, {:hex=>"10", :opcodes=>"BPL", :len=>"2", :mode=>"", :tim=>"2"}, {:hex=>"11", :opcodes=>"ORA", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"12", :opcodes=>"", :mode=>""}, {:hex=>"13", :opcodes=>"", :mode=>""}, {:hex=>"14", :opcodes=>"", :mode=>""}, {:hex=>"15", :opcodes=>"ORA", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"16", :opcodes=>"ASL", :mode=>"Zero Page, X", :len=>"2", :tim=>"6"}, {:hex=>"17", :opcodes=>"", :mode=>""}, {:hex=>"18", :opcodes=>"CLC", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"19", :opcodes=>"ORA", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"1A", :opcodes=>"", :mode=>""}, {:hex=>"1B", :opcodes=>"", :mode=>""}, {:hex=>"1C", :opcodes=>"", :mode=>""}, {:hex=>"1D", :opcodes=>"ORA", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"1E", :opcodes=>"ASL", :mode=>"Absolute, X", :len=>"3", :tim=>"7"}, {:hex=>"1F", :opcodes=>"", :mode=>""}, {:hex=>"20", :opcodes=>"JSR", :mode=>"", :len=>"3", :tim=>"6"}, {:hex=>"21", :opcodes=>"AND", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"22", :opcodes=>"", :mode=>""}, {:hex=>"23", :opcodes=>"", :mode=>""}, {:hex=>"24", :opcodes=>"BIT", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"25", :opcodes=>"AND", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"26", :opcodes=>"ROL", :mode=>"Zero Page", :len=>"2", :tim=>"5"}, {:hex=>"27", :opcodes=>"", :mode=>""}, {:hex=>"28", :len=>"1", :opcodes=>"PLP", :mode=>"", :tim=>"4"}, {:hex=>"29", :opcodes=>"AND", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"2A", :opcodes=>"ROL", :mode=>"Accumulator", :len=>"1", :tim=>"2"}, {:hex=>"2B", :opcodes=>"", :mode=>""}, {:hex=>"2C", :opcodes=>"BIT", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"2D", :opcodes=>"AND", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"2E", :opcodes=>"ROL", :mode=>"Absolute", :len=>"3", :tim=>"6"}, {:hex=>"2F", :opcodes=>"", :mode=>""}, {:hex=>"30", :opcodes=>"BMI", :len=>"2", :mode=>"", :tim=>"2"}, {:hex=>"31", :opcodes=>"AND", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"32", :opcodes=>"", :mode=>""}, {:hex=>"33", :opcodes=>"", :mode=>""}, {:hex=>"34", :opcodes=>"", :mode=>""}, {:hex=>"35", :opcodes=>"AND", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"36", :opcodes=>"ROL", :mode=>"Zero Page, X", :len=>"2", :tim=>"6"}, {:hex=>"37", :opcodes=>"", :mode=>""}, {:hex=>"38", :opcodes=>"SEC", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"39", :opcodes=>"AND", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"3A", :opcodes=>"", :mode=>""}, {:hex=>"3B", :opcodes=>"", :mode=>""}, {:hex=>"3C", :opcodes=>"", :mode=>""}, {:hex=>"3D", :opcodes=>"AND", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"3E", :opcodes=>"ROL", :mode=>"Absolute, X", :len=>"3", :tim=>"7"}, {:hex=>"3F", :opcodes=>"", :mode=>""}, {:hex=>"40", :opcodes=>"RTI", :mode=>"", :len=>"1", :tim=>"6"}, {:hex=>"41", :opcodes=>"EOR", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"42", :opcodes=>"", :mode=>""}, {:hex=>"43", :opcodes=>"", :mode=>""}, {:hex=>"44", :opcodes=>"", :mode=>""}, {:hex=>"45", :opcodes=>"EOR", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"46", :opcodes=>"LSR", :mode=>"Zero Page", :len=>"2", :tim=>"5"}, {:hex=>"47", :opcodes=>"", :mode=>""}, {:hex=>"48", :len=>"1", :opcodes=>"PHA", :mode=>"", :tim=>"3"}, {:hex=>"49", :opcodes=>"EOR", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"4A", :opcodes=>"LSR", :mode=>"Accumulator", :len=>"1", :tim=>"2"}, {:hex=>"4B", :opcodes=>"", :mode=>""}, {:hex=>"4C", :opcodes=>"JMP", :mode=>"Absolute", :len=>"3", :tim=>"3"}, {:hex=>"4D", :opcodes=>"EOR", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"4E", :opcodes=>"LSR", :mode=>"Absolute", :len=>"3", :tim=>"6"}, {:hex=>"4F", :opcodes=>"", :mode=>""}, {:hex=>"50",:len=>"2", :opcodes=>"BVC", :mode=>"", :tim=>"2"}, {:hex=>"51", :opcodes=>"EOR", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"52", :opcodes=>"", :mode=>""}, {:hex=>"53", :opcodes=>"", :mode=>""}, {:hex=>"54", :opcodes=>"", :mode=>""}, {:hex=>"55", :opcodes=>"EOR", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"56", :opcodes=>"LSR", :mode=>"Zero Page, X", :len=>"2", :tim=>"6"}, {:hex=>"57", :opcodes=>"", :mode=>""}, {:hex=>"58", :opcodes=>"CLI", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"59", :opcodes=>"EOR", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"5A", :opcodes=>"", :mode=>""}, {:hex=>"5B", :opcodes=>"", :mode=>""}, {:hex=>"5C", :opcodes=>"", :mode=>""}, {:hex=>"5D", :opcodes=>"EOR", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"5E", :opcodes=>"LSR", :mode=>"Absolute, X", :len=>"3", :tim=>"7"}, {:hex=>"5F", :opcodes=>"", :mode=>""}, {:hex=>"60", :opcodes=>"RTS", :mode=>"", :len=>"1", :tim=>"6"}, {:hex=>"61", :opcodes=>"ADC", :len=>"2", :tim=>"6", :mode=>"(Indirect, X)"}, {:hex=>"62", :opcodes=>"", :mode=>""}, {:hex=>"63", :opcodes=>"", :mode=>""}, {:hex=>"64", :opcodes=>"", :mode=>""}, {:hex=>"65", :opcodes=>"ADC", :tim=>"3", :len=>"2", :mode=>"Zero Page"}, {:hex=>"66", :opcodes=>"ROR", :mode=>"Zero Page", :len=>"2", :tim=>"5"}, {:hex=>"67", :opcodes=>"", :mode=>""}, {:hex=>"68", :len=>"1", :opcodes=>"PLA", :mode=>"", :tim=>"4"}, {:hex=>"69", :opcodes=>"ADC", :tim=>"2", :len=>"2", :mode=>"Immediate"}, {:hex=>"6A", :opcodes=>"ROR", :mode=>"Accumulator", :len=>"1", :tim=>"2"}, {:hex=>"6B", :opcodes=>"", :mode=>""}, {:hex=>"6C", :opcodes=>"JMP", :mode=>"Indirect", :len=>"3", :tim=>"5"}, {:hex=>"6D", :opcodes=>"ADC", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"6E", :opcodes=>"ROR", :mode=>"Absolute", :len=>"3", :tim=>"6"}, {:hex=>"6F", :opcodes=>"", :mode=>""}, {:hex=>"70", :len=>"2", :opcodes=>"BVS", :mode=>"", :tim=>"2"}, {:hex=>"71", :opcodes=>"ADC", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"72", :opcodes=>"", :mode=>""}, {:hex=>"73", :opcodes=>"", :mode=>""}, {:hex=>"74", :opcodes=>"", :mode=>""}, {:hex=>"75", :opcodes=>"ADC", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"76", :opcodes=>"ROR", :mode=>"Zero Page, X", :len=>"2", :tim=>"6"}, {:hex=>"77", :opcodes=>"", :mode=>""}, {:hex=>"78", :opcodes=>"SEI", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"79", :opcodes=>"ADC", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"7A", :opcodes=>"", :mode=>""}, {:hex=>"7B", :opcodes=>"", :mode=>""}, {:hex=>"7C", :opcodes=>"", :mode=>""}, {:hex=>"7D", :opcodes=>"ADC", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"7E", :opcodes=>"ROR", :mode=>"Absolute, X", :len=>"3", :tim=>"7"}, {:hex=>"7F", :opcodes=>"", :mode=>""}, {:hex=>"80", :opcodes=>"", :mode=>""}, {:hex=>"81", :opcodes=>"STA", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"82", :opcodes=>"", :mode=>""}, {:hex=>"83", :opcodes=>"", :mode=>""}, {:hex=>"84", :opcodes=>"STY", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"85", :opcodes=>"STA", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"86", :opcodes=>"STX", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"87", :opcodes=>"", :mode=>""}, {:hex=>"88", :len=>"1", :opcodes=>"DEY", :mode=>"", :tim=>"2"}, {:hex=>"89", :opcodes=>"", :mode=>""}, {:hex=>"8A", :opcodes=>"TXA", :mode=>"", :len=>"1", :tim=>"2"}, {:hex=>"8B", :opcodes=>"", :mode=>""}, {:hex=>"8C", :opcodes=>"STY", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"8D", :opcodes=>"STA", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"8E", :opcodes=>"STX", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"8F", :opcodes=>"", :mode=>""}, {:hex=>"90", :len=>"2", :opcodes=>"BCC", :mode=>"", :tim=>"2"}, {:hex=>"91", :opcodes=>"STA", :mode=>"(Indirect), Y", :len=>"2", :tim=>"6"}, {:hex=>"92", :opcodes=>"", :mode=>""}, {:hex=>"93", :opcodes=>"", :mode=>""}, {:hex=>"94", :opcodes=>"STY", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"95", :opcodes=>"STA", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"96", :opcodes=>"STX", :mode=>"Zero Page, Y", :len=>"2", :tim=>"4"}, {:hex=>"97", :opcodes=>"", :mode=>""}, {:hex=>"98", :len=>"1", :opcodes=>"TYA", :mode=>"", :tim=>"2"}, {:hex=>"99", :opcodes=>"STA", :mode=>"Absolute, Y", :len=>"3", :tim=>"5"}, {:hex=>"9A", :len=>"1", :opcodes=>"TXS", :mode=>"", :tim=>"2"}, {:hex=>"9B", :opcodes=>"", :mode=>""}, {:hex=>"9C", :opcodes=>"", :mode=>""}, {:hex=>"9D", :opcodes=>"STA", :mode=>"Absolute, X", :len=>"3", :tim=>"5"}, {:hex=>"9E", :opcodes=>"", :mode=>""}, {:hex=>"9F", :opcodes=>"", :mode=>""}, {:hex=>"A0", :opcodes=>"LDY", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"A1", :opcodes=>"LDA", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"A2", :opcodes=>"LDX", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"A3", :opcodes=>"", :mode=>""}, {:hex=>"A4", :opcodes=>"LDY", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"A5", :opcodes=>"LDA", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"A6", :opcodes=>"LDX", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"A7", :opcodes=>"", :mode=>""}, {:hex=>"A8", :len=>"1", :opcodes=>"TAY", :mode=>"", :tim=>"2"}, {:hex=>"A9", :opcodes=>"LDA", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"AA", :len=>"1", :opcodes=>"TAX", :mode=>"", :tim=>"2"}, {:hex=>"AB", :opcodes=>"", :mode=>""}, {:hex=>"AC", :opcodes=>"LDY", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"AD", :opcodes=>"LDA", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"AE", :opcodes=>"LDX", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"AF", :opcodes=>"", :mode=>""}, {:hex=>"B0", :len=>"2", :opcodes=>"BCS", :mode=>"", :tim=>"2"}, {:hex=>"B1", :opcodes=>"LDA", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"B2", :opcodes=>"", :mode=>""}, {:hex=>"B3", :opcodes=>"", :mode=>""}, {:hex=>"B4", :opcodes=>"LDY", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"B5", :opcodes=>"LDA", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"B6", :opcodes=>"LDX", :mode=>"Zero Page, Y", :len=>"2", :tim=>"4"}, {:hex=>"B7", :opcodes=>"", :mode=>""}, {:hex=>"B8", :opcodes=>"CLV", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"B9", :opcodes=>"LDA", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"BA", :len=>"1", :opcodes=>"TSX", :mode=>"", :tim=>"2"}, {:hex=>"BB", :opcodes=>"", :mode=>""}, {:hex=>"BC", :opcodes=>"LDY", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"BD", :opcodes=>"LDA", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"BE", :opcodes=>"LDX", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"BF", :opcodes=>"", :mode=>""}, {:hex=>"C0", :opcodes=>"CPY", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"C1", :opcodes=>"CMP", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"C2", :opcodes=>"", :mode=>""}, {:hex=>"C3", :opcodes=>"", :mode=>""}, {:hex=>"C4", :opcodes=>"CPY", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"C5", :opcodes=>"CMP", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"C6", :opcodes=>"DEC", :mode=>"Zero Page", :len=>"2", :tim=>"5"}, {:hex=>"C7", :opcodes=>"", :mode=>""}, {:hex=>"C8", :len=>"1", :opcodes=>"INY", :mode=>"", :tim=>"2"}, {:hex=>"C9", :opcodes=>"CMP", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"CA", :opcodes=>"DEX", :len=>"1", :mode=>"", :tim=>"2"}, {:hex=>"CB", :opcodes=>"", :mode=>""}, {:hex=>"CC", :opcodes=>"CPY", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"CD", :opcodes=>"CMP", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"CE", :opcodes=>"DEC", :mode=>"Absolute", :len=>"3", :tim=>"6"}, {:hex=>"CF", :opcodes=>"", :mode=>""}, {:hex=>"D0", :len=>"2", :opcodes=>"BNE", :mode=>"", :tim=>"2"}, {:hex=>"D1", :opcodes=>"CMP", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"D2", :opcodes=>"", :mode=>""}, {:hex=>"D3", :opcodes=>"", :mode=>""}, {:hex=>"D4", :opcodes=>"", :mode=>""}, {:hex=>"D5", :opcodes=>"CMP", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"D6", :opcodes=>"DEC", :mode=>"Zero Page, X", :len=>"2", :tim=>"6"}, {:hex=>"D7", :opcodes=>"", :mode=>""}, {:hex=>"D8", :opcodes=>"CLD", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"D9", :opcodes=>"CMP", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"DA", :opcodes=>"", :mode=>""}, {:hex=>"DB", :opcodes=>"", :mode=>""}, {:hex=>"DC", :opcodes=>"", :mode=>""}, {:hex=>"DD", :opcodes=>"CMP", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"DE", :opcodes=>"DEC", :mode=>"Absolute, X", :len=>"3", :tim=>"7"}, {:hex=>"DF", :opcodes=>"", :mode=>""}, {:hex=>"E0", :opcodes=>"CPX", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"E1", :opcodes=>"SBC", :mode=>"(Indirect, X)", :len=>"2", :tim=>"6"}, {:hex=>"E2", :opcodes=>"", :mode=>""}, {:hex=>"E3", :opcodes=>"", :mode=>""}, {:hex=>"E4", :opcodes=>"CPX", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"E5", :opcodes=>"SBC", :mode=>"Zero Page", :len=>"2", :tim=>"3"}, {:hex=>"E6", :opcodes=>"INC", :mode=>"Zero Page", :len=>"2", :tim=>"5"}, {:hex=>"E7", :opcodes=>"", :mode=>""}, {:hex=>"E8", :opcodes=>"INX", :len=>"1", :mode=>"", :tim=>"2"}, {:hex=>"E9", :opcodes=>"SBC", :mode=>"Immediate", :len=>"2", :tim=>"2"}, {:hex=>"EA", :opcodes=>"NOP", :mode=>"", :len=>"1", :tim=>"2"}, {:hex=>"EB", :opcodes=>"", :mode=>""}, {:hex=>"EC", :opcodes=>"CPX", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"ED", :opcodes=>"SBC", :mode=>"Absolute", :len=>"3", :tim=>"4"}, {:hex=>"EE", :opcodes=>"INC", :mode=>"Absolute", :len=>"3", :tim=>"6"}, {:hex=>"EF", :opcodes=>"", :mode=>""}, {:hex=>"F0", :len=>"2", :opcodes=>"BEQ", :mode=>"", :tim=>"2"}, {:hex=>"F1", :opcodes=>"SBC", :mode=>"(Indirect), Y", :len=>"2", :tim=>"5+"}, {:hex=>"F2", :opcodes=>"", :mode=>""}, {:hex=>"F3", :opcodes=>"", :mode=>""}, {:hex=>"F4", :opcodes=>"", :mode=>""}, {:hex=>"F5", :opcodes=>"SBC", :mode=>"Zero Page, X", :len=>"2", :tim=>"4"}, {:hex=>"F6", :opcodes=>"INC", :mode=>"Zero Page, X", :len=>"2", :tim=>"6"}, {:hex=>"F7", :opcodes=>"", :mode=>""}, {:hex=>"F8", :opcodes=>"SED", :len =>"1", :tim =>"2", :mode=>""}, {:hex=>"F9", :opcodes=>"SBC", :mode=>"Absolute, Y", :len=>"3", :tim=>"4+"}, {:hex=>"FA", :opcodes=>"", :mode=>""}, {:hex=>"FB", :opcodes=>"", :mode=>""}, {:hex=>"FC", :opcodes=>"", :mode=>""}, {:hex=>"FD", :opcodes=>"SBC", :mode=>"Absolute, X", :len=>"3", :tim=>"4+"}, {:hex=>"FE", :opcodes=>"INC", :mode=>"Absolute, X", :len=>"3", :tim=>"7"}, {:hex=>"FF", :opcodes=>"", :mode=>""}]
|
data/lib/ppu.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
Registers = [0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,0x4014]
|
2
|
+
|
3
|
+
class Ppu
|
4
|
+
attr_accessor :ppu
|
5
|
+
attr_accessor :registers
|
6
|
+
attr_accessor :screen
|
7
|
+
|
8
|
+
|
9
|
+
def initialize()
|
10
|
+
@ppu = [0]*0x4000
|
11
|
+
@registers = {}
|
12
|
+
Registers.each {|adresse| @registers[adresse] = 0}
|
13
|
+
init_affichage
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def init_affichage()
|
18
|
+
SDL.init SDL::INIT_VIDEO
|
19
|
+
@screen = SDL::set_video_mode 256, 240, 32, SDL::SWSURFACE
|
20
|
+
reset_pixel
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def reset_pixel()
|
25
|
+
@x = @y = 0
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def get_bit(liste_octets,ligne,bit)
|
30
|
+
return (liste_octets[ligne].bit?(7-bit) | liste_octets[ligne+8].bit?(7-bit) << 1)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_pixel(x,y)
|
34
|
+
set_tables
|
35
|
+
pos_tile = (y/8)*32+(x/8)
|
36
|
+
index = @table_nommage_screen[pos_tile] * 16
|
37
|
+
pixel = get_bit(@screen_pattern_table[index..index+15],y%8,x%8)
|
38
|
+
return pixel
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def color?(color)
|
43
|
+
rgb = case color
|
44
|
+
when 0 then [124,124,124]
|
45
|
+
when 1 then [0,0,22]
|
46
|
+
when 2 then [0,0,18]
|
47
|
+
when 3 then [64,40,188]
|
48
|
+
end
|
49
|
+
return rgb
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_tables()
|
53
|
+
@sprite_pattern_table = case @registers[0x2000].bit?(3)
|
54
|
+
when 0 then @ppu[0x0..0x0FFF]
|
55
|
+
when 1 then @ppu[0x1000..0x1FFF]
|
56
|
+
end
|
57
|
+
|
58
|
+
@screen_pattern_table = case @registers[0x2000].bit?(4)
|
59
|
+
when 0 then @ppu[0x0..0x0FFF]
|
60
|
+
when 1 then @ppu[0x1000..0x1FFF]
|
61
|
+
end
|
62
|
+
|
63
|
+
@sprite_size = @registers[0x2000].bit?(5)
|
64
|
+
|
65
|
+
@table_nommage_screen = @ppu[0x2000..0x23C0] if @registers[0x2000].bit?(1) == 0 and @registers[0x2000].bit?(0) == 0
|
66
|
+
@table_nommage_screen = @ppu[0x2400..0x27C0] if @registers[0x2000].bit?(1) == 0 and @registers[0x2000].bit?(0) == 1
|
67
|
+
@table_nommage_screen = @ppu[0x2800..0x2BC0] if @registers[0x2000].bit?(1) == 1 and @registers[0x2000].bit?(0) == 0
|
68
|
+
@table_nommage_screen = @ppu[0x2C00..0x2FC0] if @registers[0x2000].bit?(1) == 1 and @registers[0x2000].bit?(0) == 1
|
69
|
+
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def set_vblank()
|
75
|
+
@registers[0x2002] = @registers[0x2002].set_bit(7) #Set du Vblank
|
76
|
+
end
|
77
|
+
|
78
|
+
def clear_vblank()
|
79
|
+
@registers[0x2002] = @registers[0x2002].clear_bit(7) #Clear du Vblank
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def draw_screen()
|
84
|
+
@screen.putPixel(@x,@y,color?(get_pixel(@x,@y)))
|
85
|
+
@x+=1
|
86
|
+
if @x>255
|
87
|
+
@x = 0
|
88
|
+
@y+=1
|
89
|
+
elsif @y>239
|
90
|
+
reset_pixel
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/nesemul.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'nesemul'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2013-12-02'
|
5
|
+
s.summary = "NesEmul"
|
6
|
+
s.description = "Nes Emulator"
|
7
|
+
s.authors = ["Galaad Gauthier"]
|
8
|
+
s.email = 'coontail7@gmail.com'
|
9
|
+
s.files = Dir['**/*']
|
10
|
+
s.executables = ["nesemul"]
|
11
|
+
s.require_path = 'lib'
|
12
|
+
s.homepage =
|
13
|
+
'https://github.com/Galaad-Gauthier/NesEmul'
|
14
|
+
s.license = 'MIT'
|
15
|
+
s.add_dependency "json"
|
16
|
+
s.add_dependency "sdl"
|
17
|
+
end
|
data/roms/mario.nes
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nesemul
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Galaad Gauthier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sdl
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Nes Emulator
|
42
|
+
email: coontail7@gmail.com
|
43
|
+
executables:
|
44
|
+
- nesemul
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/bitwise.rb
|
49
|
+
- lib/opcodes.rb
|
50
|
+
- lib/cpu.rb
|
51
|
+
- lib/ppu.rb
|
52
|
+
- roms/mario.nes
|
53
|
+
- nesemul.gemspec
|
54
|
+
- bin/nesemul
|
55
|
+
- README.md
|
56
|
+
homepage: https://github.com/Galaad-Gauthier/NesEmul
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.0.14
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: NesEmul
|
80
|
+
test_files: []
|