c64asm 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.yardopts +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +126 -0
- data/Rakefile +6 -0
- data/c64asm.gemspec +19 -0
- data/examples/04.png +0 -0
- data/examples/04.prg +0 -0
- data/examples/hello_world.png +0 -0
- data/examples/hello_world.rb +30 -0
- data/lib/c64asm/asm.rb +751 -0
- data/lib/c64asm/basic.rb +132 -0
- data/lib/c64asm/data.rb +221 -0
- data/lib/c64asm/version.rb +7 -0
- data/lib/c64asm.rb +5 -0
- data/tools/make-data.rb +80 -0
- metadata +64 -0
data/lib/c64asm/basic.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See LICENSE.txt for licensing information.
|
3
|
+
|
4
|
+
require 'c64asm/asm'
|
5
|
+
require 'c64asm/data'
|
6
|
+
|
7
|
+
module C64Asm
|
8
|
+
class Error < Exception; end
|
9
|
+
|
10
|
+
# C64 Basic error
|
11
|
+
class BasicError < Error; end
|
12
|
+
|
13
|
+
# C64 Basic block
|
14
|
+
class Basic
|
15
|
+
attr_reader :basic, :code
|
16
|
+
|
17
|
+
# Create a new C64 basic block
|
18
|
+
def initialize(program, origin = 0x801, align = true)
|
19
|
+
raise BasicError, 'Program has to be a string' unless program.instance_of? String
|
20
|
+
raise BasicError, 'Origin has to be a fixnum' unless origin.instance_of? Fixnum
|
21
|
+
raise BasicError, 'Origin out of range' unless (origin >= 0 and origin <= 65535)
|
22
|
+
|
23
|
+
@basic = program
|
24
|
+
@code = Block.new
|
25
|
+
|
26
|
+
@code.push(Align.new(origin)) if align
|
27
|
+
@code.push(Data.new(parse(origin)))
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return a pretty string representation
|
31
|
+
def to_s; "<Basic: #{@basic.lines.to_a.length}>"; end
|
32
|
+
|
33
|
+
private
|
34
|
+
# Parse basic code string given the origin address
|
35
|
+
def parse(addr)
|
36
|
+
state = :nextline
|
37
|
+
bytes = []
|
38
|
+
line = []
|
39
|
+
token = ''
|
40
|
+
|
41
|
+
@basic.upcase.each_char do |c|
|
42
|
+
if c == "\n"
|
43
|
+
state = :nextline
|
44
|
+
next
|
45
|
+
end
|
46
|
+
|
47
|
+
if state == :nextline
|
48
|
+
unless token.empty?
|
49
|
+
token.codepoints.each{|p| bytes += [PETSCII[p]]}
|
50
|
+
token = ''
|
51
|
+
end
|
52
|
+
|
53
|
+
unless bytes.empty?
|
54
|
+
bytes += [0]
|
55
|
+
addr += 1
|
56
|
+
end
|
57
|
+
|
58
|
+
addr += 2
|
59
|
+
bytes += [addr.ls_byte, addr.ms_byte]
|
60
|
+
state = :linenum
|
61
|
+
end
|
62
|
+
|
63
|
+
if state == :linenum
|
64
|
+
if c.match(/\d/)
|
65
|
+
token += c
|
66
|
+
addr += 1
|
67
|
+
else
|
68
|
+
raise BasicError, 'Each line has to start with a line number' if token.empty?
|
69
|
+
|
70
|
+
lineno = token.to_i
|
71
|
+
raise BasicError, 'Line number out of range' unless (lineno >= 0 and lineno <= 65535)
|
72
|
+
|
73
|
+
bytes += [lineno.ls_byte, lineno.ms_byte]
|
74
|
+
addr += 2
|
75
|
+
state = :out
|
76
|
+
token = ''
|
77
|
+
|
78
|
+
next if c == ' '
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if state == :out
|
83
|
+
if c == '"'
|
84
|
+
bytes += [PETSCII['"'.ord]]
|
85
|
+
addr += 1
|
86
|
+
state = :in
|
87
|
+
|
88
|
+
next
|
89
|
+
elsif c == ' '
|
90
|
+
unless token.empty?
|
91
|
+
token.codepoints.each{|p| bytes += [PETSCII[p]]}
|
92
|
+
token = ''
|
93
|
+
end
|
94
|
+
|
95
|
+
bytes += [PETSCII[' '.ord]]
|
96
|
+
addr += 1
|
97
|
+
elsif BASIC.has_key? c
|
98
|
+
token.codepoints.each{|p| bytes += [PETSCII[p]]} unless token.empty?
|
99
|
+
bytes += [BASIC[c]]
|
100
|
+
addr += 1
|
101
|
+
token = ''
|
102
|
+
else
|
103
|
+
raise BasicError, 'Unknown character' unless PETSCII.has_key? c.codepoints.to_a.first
|
104
|
+
|
105
|
+
token += c
|
106
|
+
addr += 1
|
107
|
+
|
108
|
+
if BASIC.has_key? token
|
109
|
+
bytes += [BASIC[token]]
|
110
|
+
token = ''
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
if state == :in
|
116
|
+
raise BasicError, 'Unknown character' unless PETSCII.has_key? c.codepoints.to_a.first
|
117
|
+
|
118
|
+
token += c
|
119
|
+
addr += 1
|
120
|
+
state = :out if c == '"'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
unless token.empty?
|
125
|
+
token.codepoints.each{|p| bytes += [PETSCII[p]]}
|
126
|
+
bytes += [0]
|
127
|
+
end
|
128
|
+
|
129
|
+
bytes += [0, 0]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/c64asm/data.rb
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See LICENSE.txt for licensing information.
|
3
|
+
|
4
|
+
module C64Asm
|
5
|
+
# Known addressing modes
|
6
|
+
ADDR_MODES = {
|
7
|
+
:n => { :src => '', :len => 0 },
|
8
|
+
:d => { :src => ' #%s', :len => 1},
|
9
|
+
:z => { :src => ' %s', :len => 1},
|
10
|
+
:zx => { :src => ' %s,x', :len => 1},
|
11
|
+
:zy => { :src => ' %s,y', :len => 1},
|
12
|
+
:zxr => { :src => ' (%s,z)', :len => 1},
|
13
|
+
:zyr => { :src => ' (%s),y', :len => 1},
|
14
|
+
:a => { :src => ' %s', :len => 2},
|
15
|
+
:ax => { :src => ' %s,x', :len => 2},
|
16
|
+
:ay => { :src => ' %s,y', :len => 2},
|
17
|
+
:ar => { :src => ' (%s)', :len => 2},
|
18
|
+
:r => { :src => ' %s', :len => 1},
|
19
|
+
:e => { :src => '', :len => 1}
|
20
|
+
}
|
21
|
+
|
22
|
+
# Known operands
|
23
|
+
OP_CODES = {
|
24
|
+
:adc=>{:d=>{:byte=>105, :cycles=>2},
|
25
|
+
:z=>{:byte=>101, :cycles=>3},
|
26
|
+
:zx=>{:byte=>117, :cycles=>4},
|
27
|
+
:zxr=>{:byte=>97, :cycles=>6},
|
28
|
+
:zyr=>{:byte=>113, :cycles=>5, :page=>true},
|
29
|
+
:a=>{:byte=>109, :cycles=>4},
|
30
|
+
:ax=>{:byte=>125, :cycles=>4, :page=>true},
|
31
|
+
:ay=>{:byte=>121, :cycles=>4, :page=>true}},
|
32
|
+
:and=>{:d=>{:byte=>41, :cycles=>2},
|
33
|
+
:z=>{:byte=>37, :cycles=>3},
|
34
|
+
:zx=>{:byte=>53, :cycles=>4},
|
35
|
+
:zxr=>{:byte=>33, :cycles=>6},
|
36
|
+
:zyr=>{:byte=>49, :cycles=>5, :page=>true},
|
37
|
+
:a=>{:byte=>45, :cycles=>4},
|
38
|
+
:ax=>{:byte=>61, :cycles=>4, :page=>true},
|
39
|
+
:ay=>{:byte=>41, :cycles=>4, :page=>true},
|
40
|
+
:e=>{:cycles=>2}},
|
41
|
+
:asl=>{:z=>{:byte=>6, :cycles=>5},
|
42
|
+
:zx=>{:byte=>22, :cycles=>6},
|
43
|
+
:a=>{:byte=>14, :cycles=>6},
|
44
|
+
:ax=>{:byte=>30, :cycles=>7},
|
45
|
+
:e=>{:byte=>10}},
|
46
|
+
:bcc=>{:r=>{:byte=>144, :cycles=>2, :page=>true, :branch=>true}},
|
47
|
+
:bcs=>{:r=>{:byte=>176, :cycles=>2, :page=>true, :branch=>true}},
|
48
|
+
:beq=>{:r=>{:byte=>240, :cycles=>2, :page=>true, :branch=>true}},
|
49
|
+
:bit=>{:d=>{:byte=>36, :cycles=>3}, :zyr=>{:byte=>44, :cycles=>4}},
|
50
|
+
:bmi=>{:r=>{:byte=>48, :cycles=>2, :page=>true, :branch=>true}},
|
51
|
+
:bne=>{:r=>{:byte=>208, :cycles=>2, :page=>true, :branch=>true}},
|
52
|
+
:bpl=>{:r=>{:byte=>16, :cycles=>2, :page=>true, :branch=>true}},
|
53
|
+
:brk=>{:n=>{:byte=>0, :cycles=>7}},
|
54
|
+
:bvc=>{:r=>{:byte=>80, :cycles=>2, :page=>true, :branch=>true}},
|
55
|
+
:bvs=>{:r=>{:byte=>112, :cycles=>2, :page=>true, :branch=>true}},
|
56
|
+
:clc=>{:n=>{:byte=>24, :cycles=>2}},
|
57
|
+
:cld=>{:n=>{:byte=>216, :cycles=>2}},
|
58
|
+
:cli=>{:n=>{:byte=>88, :cycles=>2}},
|
59
|
+
:clv=>{:n=>{:byte=>184, :cycles=>2}},
|
60
|
+
:cmp=>{:d=>{:byte=>201, :cycles=>2},
|
61
|
+
:z=>{:byte=>197, :cycles=>3},
|
62
|
+
:zx=>{:byte=>213, :cycles=>4},
|
63
|
+
:zxr=>{:byte=>193, :cycles=>6},
|
64
|
+
:zyr=>{:byte=>209, :cycles=>5, :page=>true},
|
65
|
+
:a=>{:byte=>205, :cycles=>4},
|
66
|
+
:ax=>{:byte=>221, :cycles=>4, :page=>true},
|
67
|
+
:ay=>{:byte=>217, :cycles=>4, :page=>true}},
|
68
|
+
:cpx=>{:d=>{:byte=>224, :cycles=>2},
|
69
|
+
:z=>{:byte=>228, :cycles=>3},
|
70
|
+
:a=>{:byte=>236, :cycles=>4}},
|
71
|
+
:cpy=>{:d=>{:byte=>192, :cycles=>2},
|
72
|
+
:z=>{:byte=>196, :cycles=>3},
|
73
|
+
:a=>{:byte=>204, :cycles=>4}},
|
74
|
+
:dec=>{:z=>{:byte=>198, :cycles=>5},
|
75
|
+
:zx=>{:byte=>214, :cycles=>6},
|
76
|
+
:a=>{:byte=>206, :cycles=>6},
|
77
|
+
:ax=>{:byte=>222, :cycles=>7}},
|
78
|
+
:dex=>{:n=>{:byte=>202, :cycles=>2}},
|
79
|
+
:dey=>{:n=>{:byte=>136, :cycles=>2}},
|
80
|
+
:eor=>{:d=>{:byte=>73, :cycles=>2},
|
81
|
+
:z=>{:byte=>69, :cycles=>3},
|
82
|
+
:zx=>{:byte=>85, :cycles=>4},
|
83
|
+
:zxr=>{:byte=>65, :cycles=>6},
|
84
|
+
:zyr=>{:byte=>81, :cycles=>5, :page=>true},
|
85
|
+
:a=>{:byte=>77, :cycles=>4},
|
86
|
+
:ax=>{:byte=>93, :cycles=>4, :page=>true},
|
87
|
+
:ay=>{:byte=>89, :cycles=>4, :page=>true}},
|
88
|
+
:inc=>{:z=>{:byte=>230, :cycles=>5},
|
89
|
+
:zx=>{:byte=>246, :cycles=>6},
|
90
|
+
:a=>{:byte=>238, :cycles=>6},
|
91
|
+
:ax=>{:byte=>254, :cycles=>7}},
|
92
|
+
:inx=>{:n=>{:byte=>232, :cycles=>2}},
|
93
|
+
:iny=>{:n=>{:byte=>200, :cycles=>2}},
|
94
|
+
:jmp=>{:a=>{:byte=>76, :cycles=>3}, :ar=>{:byte=>108, :cycles=>5}},
|
95
|
+
:jsr=>{:a=>{:byte=>32, :cycles=>6}},
|
96
|
+
:lda=>{:d=>{:byte=>169, :cycles=>2},
|
97
|
+
:z=>{:byte=>165, :cycles=>3},
|
98
|
+
:zx=>{:byte=>181, :cycles=>4},
|
99
|
+
:zxr=>{:byte=>161, :cycles=>6},
|
100
|
+
:zyr=>{:byte=>177, :cycles=>5, :page=>true},
|
101
|
+
:a=>{:byte=>173, :cycles=>4},
|
102
|
+
:ax=>{:byte=>189, :cycles=>4, :page=>true},
|
103
|
+
:ay=>{:byte=>185, :cycles=>4, :page=>true}},
|
104
|
+
:ldx=>{:d=>{:byte=>162, :cycles=>2},
|
105
|
+
:z=>{:byte=>166, :cycles=>3},
|
106
|
+
:zy=>{:byte=>182, :cycles=>4},
|
107
|
+
:a=>{:byte=>174, :cycles=>4},
|
108
|
+
:ay=>{:byte=>190, :cycles=>4, :page=>true}},
|
109
|
+
:ldy=>{:d=>{:byte=>160, :cycles=>2},
|
110
|
+
:z=>{:byte=>164, :cycles=>3},
|
111
|
+
:zx=>{:byte=>180, :cycles=>4},
|
112
|
+
:a=>{:byte=>172, :cycles=>4},
|
113
|
+
:ax=>{:byte=>188, :cycles=>4, :page=>true}},
|
114
|
+
:lsr=>{:z=>{:byte=>70, :cycles=>5},
|
115
|
+
:zx=>{:byte=>86, :cycles=>6},
|
116
|
+
:a=>{:byte=>78, :cycles=>6},
|
117
|
+
:ax=>{:byte=>94, :cycles=>7},
|
118
|
+
:e=>{:byte=>74, :cycles=>2}},
|
119
|
+
:nop=>{:n=>{:byte=>234, :cycles=>2}},
|
120
|
+
:ora=>{:d=>{:byte=>9, :cycles=>2},
|
121
|
+
:z=>{:byte=>5, :cycles=>3},
|
122
|
+
:zx=>{:byte=>21, :cycles=>4},
|
123
|
+
:zxr=>{:byte=>1, :cycles=>6},
|
124
|
+
:zyr=>{:byte=>17, :cycles=>5, :page=>true},
|
125
|
+
:a=>{:byte=>13, :cycles=>4},
|
126
|
+
:ax=>{:byte=>29, :cycles=>4, :page=>true},
|
127
|
+
:ay=>{:byte=>25, :cycles=>4, :page=>true}},
|
128
|
+
:pha=>{:n=>{:byte=>72, :cycles=>3}},
|
129
|
+
:php=>{:n=>{:byte=>8, :cycles=>3}},
|
130
|
+
:pla=>{:n=>{:byte=>104, :cycles=>4}},
|
131
|
+
:plp=>{:n=>{:byte=>40, :cycles=>4}},
|
132
|
+
:rol=>{:z=>{:byte=>38, :cycles=>5},
|
133
|
+
:zx=>{:byte=>54, :cycles=>6},
|
134
|
+
:a=>{:byte=>46, :cycles=>6},
|
135
|
+
:ax=>{:byte=>62, :cycles=>7},
|
136
|
+
:e=>{:byte=>42, :cycles=>2}},
|
137
|
+
:ror=>{:z=>{:byte=>102, :cycles=>5},
|
138
|
+
:zx=>{:byte=>118, :cycles=>6},
|
139
|
+
:a=>{:byte=>110, :cycles=>6},
|
140
|
+
:ax=>{:byte=>126, :cycles=>7},
|
141
|
+
:e=>{:byte=>106, :cycles=>2}},
|
142
|
+
:rti=>{:n=>{:byte=>64, :cycles=>6}},
|
143
|
+
:rts=>{:n=>{:byte=>96, :cycles=>6}},
|
144
|
+
:sbc=>{:d=>{:byte=>233, :cycles=>2},
|
145
|
+
:z=>{:byte=>229, :cycles=>3},
|
146
|
+
:zx=>{:byte=>245, :cycles=>4},
|
147
|
+
:zxr=>{:byte=>225, :cycles=>6},
|
148
|
+
:zyr=>{:byte=>241, :cycles=>5, :page=>true},
|
149
|
+
:a=>{:byte=>237, :cycles=>4},
|
150
|
+
:ax=>{:byte=>253, :cycles=>4, :page=>true},
|
151
|
+
:ay=>{:byte=>233, :cycles=>4, :page=>true}},
|
152
|
+
:sec=>{:n=>{:byte=>56, :cycles=>2}},
|
153
|
+
:sed=>{:n=>{:byte=>248, :cycles=>2}},
|
154
|
+
:sei=>{:n=>{:byte=>120, :cycles=>2}},
|
155
|
+
:sta=>{:z=>{:byte=>133, :cycles=>3},
|
156
|
+
:zx=>{:byte=>149, :cycles=>4},
|
157
|
+
:zxr=>{:byte=>129, :cycles=>6},
|
158
|
+
:zyr=>{:byte=>145, :cycles=>6},
|
159
|
+
:a=>{:byte=>141, :cycles=>4},
|
160
|
+
:ax=>{:byte=>157, :cycles=>5},
|
161
|
+
:ay=>{:byte=>153, :cycles=>5}},
|
162
|
+
:stx=>{:z=>{:byte=>134, :cycles=>3},
|
163
|
+
:zy=>{:byte=>150, :cycles=>4},
|
164
|
+
:a=>{:byte=>142, :cycles=>4}},
|
165
|
+
:sty=>{:z=>{:byte=>132, :cycles=>3},
|
166
|
+
:zx=>{:byte=>148, :cycles=>4},
|
167
|
+
:a=>{:byte=>140, :cycles=>4}},
|
168
|
+
:tax=>{:n=>{:byte=>170, :cycles=>2}},
|
169
|
+
:tay=>{:n=>{:byte=>168, :cycles=>2}},
|
170
|
+
:tsx=>{:n=>{:byte=>186, :cycles=>2}},
|
171
|
+
:txa=>{:n=>{:byte=>138, :cycles=>2}},
|
172
|
+
:txs=>{:n=>{:byte=>154, :cycles=>2}},
|
173
|
+
:tya=>{:n=>{:byte=>152, :cycles=>2}}}
|
174
|
+
|
175
|
+
# Character map
|
176
|
+
CHAR_MAP = {
|
177
|
+
64=>0, 65=>1, 66=>2, 67=>3, 68=>4, 69=>5, 70=>6, 71=>7, 72=>8, 73=>9, 74=>10, 75=>11, 76=>12,
|
178
|
+
77=>13, 78=>14, 79=>15, 80=>16, 81=>17, 82=>18, 83=>19, 84=>20, 85=>21, 86=>22, 87=>23, 88=>24,
|
179
|
+
89=>25, 90=>26, 91=>27, 163=>28, 93=>29, 8593=>30, 8592=>31, 32=>32, 33=>33, 34=>34, 35=>35,
|
180
|
+
36=>36, 37=>37, 38=>38, 39=>39, 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47,
|
181
|
+
48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59,
|
182
|
+
60=>60, 61=>61, 62=>62, 63=>63
|
183
|
+
}
|
184
|
+
|
185
|
+
# PETSCII map
|
186
|
+
PETSCII = {
|
187
|
+
32=>32, 160=>224, 38=>38, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 39=>39, 40=>40, 41=>41, 42=>42,
|
188
|
+
43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54,
|
189
|
+
55=>55, 56=>56, 57=>57, 58=>58, 59=>59, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67,
|
190
|
+
68=>68, 69=>69, 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79,
|
191
|
+
80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89, 90=>90, 91=>91,
|
192
|
+
92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99, 100=>100, 101=>101, 102=>102,
|
193
|
+
103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109, 110=>110, 111=>111, 112=>112,
|
194
|
+
113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119, 120=>120, 121=>121, 122=>122,
|
195
|
+
123=>123, 124=>124, 125=>125, 126=>126, 127=>127, 61700=>129, 61712=>133, 61714=>134, 61716=>135,
|
196
|
+
61718=>136, 61713=>137, 61715=>138, 61717=>139, 61719=>140, 10=>141, 61701=>144, 61726=>145, 61723=>146,
|
197
|
+
61729=>148, 61702=>149, 61703=>150, 61704=>151, 61705=>152, 61706=>153, 61707=>154, 61708=>155, 61709=>156,
|
198
|
+
61725=>157, 61710=>158, 61711=>159, 9612=>225, 9604=>226, 9620=>227, 9601=>228, 9615=>229, 9618=>230,
|
199
|
+
9621=>231, 61743=>232, 9700=>233, 61744=>234, 9500=>235, 61748=>236, 9492=>237, 9488=>238, 9602=>239,
|
200
|
+
9484=>240, 9524=>241, 9516=>242, 9508=>243, 9614=>244, 9613=>245, 61745=>246, 61746=>247, 61747=>248,
|
201
|
+
9603=>249, 61741=>250, 61749=>251, 61750=>252, 9496=>253, 61751=>254, 61752=>191, 9473=>195, 9824=>193,
|
202
|
+
9474=>221, 61730=>196, 61731=>197, 61732=>198, 61734=>199, 61736=>200, 9582=>201, 9584=>202, 9583=>203,
|
203
|
+
61738=>204, 9586=>205, 9585=>206, 61739=>207, 61740=>208, 9679=>209, 61733=>210, 9829=>211, 61735=>212,
|
204
|
+
9581=>213, 9587=>214, 9675=>215, 9827=>216, 61737=>217, 9830=>218, 9532=>219, 61742=>220, 960=>255,
|
205
|
+
9701=>223
|
206
|
+
}
|
207
|
+
|
208
|
+
# Basic commands
|
209
|
+
BASIC = {
|
210
|
+
"END"=>128, "FOR"=>129, "NEXT"=>130, "DATA"=>131, "INPUT#"=>132, "INPUT"=>133, "DIM"=>134, "READ"=>135,
|
211
|
+
"LET"=>136, "GOTO"=>137, "RUN"=>138, "IF"=>139, "RESTORE"=>140, "GOSUB"=>141, "RETURN"=>142, "REM"=>143,
|
212
|
+
"STOP"=>144, "ON"=>145, "WAIT"=>146, "LOAD"=>147, "SAVE"=>148, "VERIFY"=>149, "DEF"=>150, "POKE"=>151,
|
213
|
+
"PRINT#"=>152, "PRINT"=>153, "CONT"=>154, "LIST"=>155, "CLR"=>156, "CMD"=>157, "SYS"=>158, "OPEN"=>159,
|
214
|
+
"CLOSE"=>160, "GET"=>161, "NEW"=>162, "TAB("=>163, "TO"=>164, "FN"=>165, "SPC("=>166, "THEN"=>167,
|
215
|
+
"NOT"=>168, "STEP"=>169, "+"=>170, "-"=>171, "*"=>172, "/"=>173, "^"=>174, "AND"=>175, "OR"=>176,
|
216
|
+
">"=>177, "="=>178, "<"=>179, "SGN"=>180, "INT"=>181, "ABS"=>182, "USR"=>183, "FRE"=>184, "POS"=>185,
|
217
|
+
"SQR"=>186, "RND"=>187, "LOG"=>188, "EXP"=>189, "COS"=>190, "SIN"=>191, "TAN"=>192, "ATN"=>193,
|
218
|
+
"PEEK"=>194, "LEN"=>195, "STR$"=>196, "VAL"=>197, "ASC"=>198, "CHR$"=>199, "LEFT$"=>200, "RIGHT$"=>201,
|
219
|
+
"MID$"=>202, "GO"=>203
|
220
|
+
}
|
221
|
+
end
|
data/lib/c64asm.rb
ADDED
data/tools/make-data.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
# See LICENSE.txt for licensing information.
|
4
|
+
|
5
|
+
# I assume I've used this to get the contents of what is now lib/data.rb.
|
6
|
+
# Data-driven assembly ftw!
|
7
|
+
#
|
8
|
+
# Honestly, I leave it as close to as it were two years ago as I can.
|
9
|
+
# Perlish stuff.
|
10
|
+
|
11
|
+
%w{ pp open-uri nokogiri }.each{|g| require g}
|
12
|
+
|
13
|
+
MODES = %w{ n d z zx zy zxr zyr a ax ay ar r e }
|
14
|
+
|
15
|
+
puts "MODES = [ #{MODES.collect{|m| ":#{m}"}.join(', ')} ]\n"
|
16
|
+
|
17
|
+
opcodes = Hash.new
|
18
|
+
page = Nokogiri::HTML.parse(open('http://sta.c64.org/cbm64mcinst2.html'))
|
19
|
+
page.xpath('//tr').each do |row|
|
20
|
+
data = row.xpath('td').collect{|c| c.content}
|
21
|
+
next unless data.length == 14
|
22
|
+
inst = data.shift.downcase.to_sym
|
23
|
+
opcodes[inst] = Hash.new
|
24
|
+
data.each_with_index do |code, i|
|
25
|
+
next if code[0] != '$'
|
26
|
+
mode = MODES[i].to_sym
|
27
|
+
op = code.gsub(/\$/, '').to_i(16)
|
28
|
+
opcodes[inst][mode] = Hash.new
|
29
|
+
opcodes[inst][mode][:byte] = op
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
page = Nokogiri::HTML.parse(open('http://sta.c64.org/cbm64mctime.html'))
|
34
|
+
page.xpath('//tr').each do |row|
|
35
|
+
data = row.xpath('td').collect{|c| c.content}
|
36
|
+
next unless data.length == 14
|
37
|
+
inst = data.shift.downcase.to_sym
|
38
|
+
data.each_with_index do |code, i|
|
39
|
+
next unless m = code.match(/(\d)(\+)?(\*)?/)
|
40
|
+
cycles = m[1].to_i
|
41
|
+
boundary = m[2] ? true : false
|
42
|
+
branch = m[3] ? true : false
|
43
|
+
mode = MODES[i].to_sym
|
44
|
+
#puts "#{inst} #{mode} #{cycles} #{boundary} #{branch}"
|
45
|
+
opcodes[inst][mode] ||= Hash.new
|
46
|
+
opcodes[inst][mode][:cycles] = cycles
|
47
|
+
opcodes[inst][mode][:page] = true if boundary
|
48
|
+
opcodes[inst][mode][:branch] = true if branch
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
puts 'OPCODES = '
|
53
|
+
pp(opcodes, width = 120)
|
54
|
+
|
55
|
+
petscii = Hash.new
|
56
|
+
page = Nokogiri::HTML.parse(open('http://www.andrijar.com/tables/petsci.htm'))
|
57
|
+
page.xpath('//tr').each do |row|
|
58
|
+
data = row.xpath('td').collect{|c| c.content}
|
59
|
+
0.step(11, 3).each do |i|
|
60
|
+
byte = data[i].to_i
|
61
|
+
symbol = data[i+2]
|
62
|
+
next if (symbol == 'NOC' or symbol == '')
|
63
|
+
point = symbol.unpack('U*').first
|
64
|
+
petscii[point] = byte
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
puts 'PETSCII = '
|
69
|
+
pp(petscii, width = 120)
|
70
|
+
|
71
|
+
# for basic tokens
|
72
|
+
#tokens = {}
|
73
|
+
#STDIN.each_line do |l|
|
74
|
+
# code, *rest = l.split(' ')
|
75
|
+
# byte = code.split('/').first
|
76
|
+
# name = rest.first.split(' ').first
|
77
|
+
# tokens[name] = byte.to_i
|
78
|
+
#end
|
79
|
+
#
|
80
|
+
#pp(tokens, width=120)
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: c64asm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Piotr S. Staszewski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Already two-year-old project inspirated by the NES assembler written
|
14
|
+
in Lisp. The assembly DSL lets you easily unroll loops, create screen maps on the
|
15
|
+
fly and just hack the thing. As you write a plain .prg file you may also dump the
|
16
|
+
code to a very verbose format to ponder the machine code.
|
17
|
+
email: p.staszewski@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".gitignore"
|
23
|
+
- ".yardopts"
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- c64asm.gemspec
|
28
|
+
- examples/04.png
|
29
|
+
- examples/04.prg
|
30
|
+
- examples/hello_world.png
|
31
|
+
- examples/hello_world.rb
|
32
|
+
- lib/c64asm.rb
|
33
|
+
- lib/c64asm/asm.rb
|
34
|
+
- lib/c64asm/basic.rb
|
35
|
+
- lib/c64asm/data.rb
|
36
|
+
- lib/c64asm/version.rb
|
37
|
+
- tools/make-data.rb
|
38
|
+
homepage: https://github.com/drbig/c64asm
|
39
|
+
licenses:
|
40
|
+
- BSD
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.8.7
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.2.2
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Data-driven verbose DSL (almost dis-)assembler for MOS6502 with focus on
|
62
|
+
Commoder 64
|
63
|
+
test_files: []
|
64
|
+
has_rdoc:
|