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