nesemul 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,13 @@
1
+ #NesEmul
2
+
3
+ *Requires* : ruby/sdl
4
+
5
+ *Install Nesemul*
6
+
7
+ ~~~
8
+ $ gem install nesemul
9
+ ~~~
10
+
11
+ ~~~
12
+ $ nesemul <Your file>
13
+ ~~~
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: []