diff --git a/6502.lua b/6502.lua index 94261b1..4b3d218 100644 --- a/6502.lua +++ b/6502.lua @@ -277,6 +277,7 @@ M.location = function(start, finish) end location.start = start[1] location.finish = start[2] + location.name = start.name location.rorg = start.rorg if type(location.rorg) == 'number' then local offset = location.rorg - location.start diff --git a/l65.lua b/l65.lua index 870105b..1e1c676 100644 --- a/l65.lua +++ b/l65.lua @@ -54,6 +54,7 @@ local Keywords_6502 = { 'lax', 'rla', 'rra', 'sax', 'sbx', 'sha', 'shs', 'shx', 'shy', 'slo', 'sre', } +local Registers_6502 = { a=8, x=8, y=8 } local syntax6502_on local function syntax6502(on) @@ -64,6 +65,11 @@ local function syntax6502(on) end syntax6502(true) +local syntax6502k_on +local function syntax6502k(on) + syntax6502k_on = on +end + local opcode_arg_encapsulate_on local function opcode_arg_encapsulate(on) opcode_arg_encapsulate_on = not opcode_arg_encapsulate_on @@ -257,6 +263,15 @@ local function LexLua(src) repeat get() c = peek() until not (UpperChars[c] or LowerChars[c] or Digits[c] or c == '_') return src:sub(start, p-1) end + local function peek_ident(i, spaces) + if not spaces then spaces = Spaces end + local c + while true do c=peek(i) if not spaces[c] then break end i=i+1 end + if not (UpperChars[c] or LowerChars[c] or c == '_') then return end + local start = p+i + repeat i=i+1 c = peek(i) until not (UpperChars[c] or LowerChars[c] or Digits[c] or c == '_') + return src:sub(start, p+i-1),i,c + end --shared stuff local function generateError(err) @@ -454,6 +469,9 @@ local function LexLua(src) if dat == 'syntax6502' then onoff(syntax6502) toEmit = {Type = 'Symbol', Data = ';'} + elseif dat == 'syntax6502k' then + onoff(syntax6502k) + toEmit = {Type = 'Symbol', Data = ';'} elseif dat == 'encapsulate' then onoff(function() end) toEmit = {Type = 'Keyword', Data = 'encapsulate_' .. opt} @@ -476,7 +494,35 @@ local function LexLua(src) if Keywords[dat] then toEmit = {Type = 'Keyword', Data = dat} else - toEmit = {Type = 'Ident', Data = dat} + if syntax6502k_on then + local i=0 + while true do c=peek(i) if not Spaces[c] then break end i=i+1 end + if c == '=' then + local idents,ident = {dat} + repeat + i = i+1 + ident,i,c = peek_ident(i) + if not ident then break end + table.insert(idents, ident) + until c ~= '=' + local reg = idents[#idents] + if Registers_6502[reg] then + -- list of assignements ends with =a, =x, or =y + get_n(i) + -- TODO find a=expr, emit lda expr + local st = 'st'..reg + idents[#idents] = nil + toEmit = {} + for k,v in ipairs(idents) do + table.insert(toEmit, { Type='Keyword', Data=st }) + table.insert(toEmit, { Type='Ident', Data=v }) + end + end + end + end + if not toEmit then + toEmit = {Type = 'Ident', Data = dat} + end end elseif Digits[c] or (peek() == '.' and Digits[peek(1)]) then @@ -594,21 +640,33 @@ local function LexLua(src) end end - --add the emitted symbol, after adding some common data - toEmit.LeadingWhite = leading -- table of leading whitespace/comments - --for k, tok in pairs(leading) do - -- tokens[#tokens + 1] = tok - --end + if toEmit[1] then + toEmit[1].LeadingWhite = leading + for k,v in ipairs(toEmit) do + v.Line = thisLine + v.Char = thisChar + v.Print = function() + return "<"..(v.Type..string.rep(' ', 7-#v.Type)).." "..(v.Data or '').." >" + end + tokens[#tokens+1] = v + end + else + --add the emitted symbol, after adding some common data + toEmit.LeadingWhite = leading -- table of leading whitespace/comments + --for k, tok in pairs(leading) do + -- tokens[#tokens + 1] = tok + --end - toEmit.Line = thisLine - toEmit.Char = thisChar - toEmit.Print = function() - return "<"..(toEmit.Type..string.rep(' ', 7-#toEmit.Type)).." "..(toEmit.Data or '').." >" + toEmit.Line = thisLine + toEmit.Char = thisChar + toEmit.Print = function() + return "<"..(toEmit.Type..string.rep(' ', 7-#toEmit.Type)).." "..(toEmit.Data or '').." >" + end + tokens[#tokens+1] = toEmit + + --halt after eof has been emitted + if toEmit.Type == 'Eof' then break end end - tokens[#tokens+1] = toEmit - - --halt after eof has been emitted - if toEmit.Type == 'Eof' then break end end end) if not st then diff --git a/samples/vcs1k.l65 b/samples/vcs1k.l65 new file mode 100644 index 0000000..715a671 --- /dev/null +++ b/samples/vcs1k.l65 @@ -0,0 +1,35 @@ +require'vcs' + +#pragma syntax6502k on + +TIM_OVERSCAN = 50 -- TIM64T, 3200 cycles = ~ 42 scanlines +TIM_VBLANK = 61 -- TIM64T, 3904 cycles = ~ 51 scanlines +TIM_KERNEL = 17 -- T1024T, 17408 cycles = ~229 scanlines + +location(0xf000, 0xffff) + +section{'vectors', org=0xfffc} dc.w start,start + +local kernel = function() + ldx#0xd0 @_loop sta WSYNC stx COLUBK dex bne _loop +end + +local wait = function() local l=label() lda INTIM bne l end + +@@start + -- clear zeropage + cld ldx#0 txa @_clear dex tsx pha bne _clear +@main + -- overscan + WSYNC=a lda#2 VBLANK=a lda#TIM_OVERSCAN sta TIM64T wait() + -- vblank + lda#0b1110 @_vsync sta WSYNC sta VSYNC lsr bne _vsync + lda#2 sta VBLANK lda#TIM_VBLANK sta TIM64T wait() sta WSYNC sta VBLANK + -- kernel + lda#TIM_KERNEL sta T1024T kernel() wait() + jmp main + +local filename=string.match(arg[0], ".-([^\\/]-)%.?[^%.\\/]*$") +writebin(filename..'.bin') +writesym(filename..'.sym') +print(stats) diff --git a/vcs.lua b/vcs.lua index 7fa92e0..3d7389d 100644 --- a/vcs.lua +++ b/vcs.lua @@ -83,3 +83,8 @@ do local symbols = cpu.symbols for k,v in pairs(vcs) do symbols[k] = v end end +-- forbid globals of same key as system address constants +cpu.__newindex = function(t,k,v) + if vcs[k] then error("attempt to modify read only symbol " .. k) end + rawset(t,k,v) +end diff --git a/vcs_test.l65 b/vcs_test.l65 deleted file mode 100644 index dead65c..0000000 --- a/vcs_test.l65 +++ /dev/null @@ -1,45 +0,0 @@ -dofile "vcs.lua" - -TIM_OVERSCAN = 50 -- TIM64T, 3200 cycles = ~ 42 scanlines -TIM_VBLANK = 61 -- TIM64T, 3904 cycles = ~ 51 scanlines -TIM_KERNEL = 17 -- T1024T, 17408 cycles = ~229 scanlines - -location(0xf000, 0xffff) - -section waitForIntim - lda INTIM - bne waitForIntim - rts - --- alternate syntax -section waitForIntim - { a=INTIM }!= - rts - -section waitForIntim - repeat a=INTIM until N - @{ a=INTIM }~0 - rts - --- interop: generate stubs at fixed addresses --- stub(0xff10, waitForIntim[, altname]) --- and dumps all generated code/data into opaque data - -function inca() asm("clc; adc #0") end -section "testMacro" { - lda #0 - inca() -} -=> -section("testMacro") -label("testMacro") -lda{imm=0} -inca() - => - clc() - adc{imm=0} -endsection() - - -require_ "6502-def" - diff --git a/vcs_test.lua b/vcs_test.lua deleted file mode 100644 index 18326d0..0000000 --- a/vcs_test.lua +++ /dev/null @@ -1,57 +0,0 @@ -dofile "vcs.lua" - -TIM_OVERSCAN = 50 -- TIM64T, 3200 cycles = ~ 42 scanlines -TIM_VBLANK = 61 -- TIM64T, 3904 cycles = ~ 51 scanlines -TIM_KERNEL = 17 -- T1024T, 17408 cycles = ~229 scanlines - -location(0xf000, 0xffff) - -section "waitForIntim" - -- n_{ a=INTIM } ? - lda(INTIM) -- or a=INTIM - bne "waitForIntim" - rts - -section "doOverscan" - sta{WSYNC} -- WSYNC=a - lda(2) sta{VBLANK} -- a=2 VBLANK=a - lda(TIM_OVERSCAN) sta{TIM64T} -- a=TIM_OVERSCAN TIM64T=a - jsr "waitForIntim" - -section "doVBlank" - lda(0x0e) - label ".vsyncLoop" - sta{WSYNC} - sta{VSYNC} - lsr() - bne ".vsyncLoop" - lda(2) - sta{VBLANK} - lda(TIM_VBLANK) - sta{TIM64T} - jsr "waitForIntim" - -section "doKernel" - lda(TIM_KERNEL) - sta{T1024T} - jsr "waitForIntim" - -section "start" - -- clear zeropage - cld() - ldx(0) - txa() - label ".clearLoop" - dex() - tsx() - pha() - bne ".clearLoop" - -- main - label "mainLoop" - jsr "doOverscan" - jsr "doVBlank" - jsr "doKernel" - jmp "mainLoop" - -section{ name="vectors", org=0xfffc } - word{ "start", "start" }