mirror of
https://github.com/g012/l65.git
synced 2025-08-15 17:27:17 +00:00
Sections now generate regular labels for themselves.
This commit is contained in:
194
6502.lua
194
6502.lua
@@ -2,6 +2,7 @@ local M = {}
|
|||||||
|
|
||||||
local symbols={} M.symbols=symbols
|
local symbols={} M.symbols=symbols
|
||||||
local locations={} M.locations=locations
|
local locations={} M.locations=locations
|
||||||
|
local sections={} M.sections=sections
|
||||||
local stats={} M.stats=stats setmetatable(stats, stats)
|
local stats={} M.stats=stats setmetatable(stats, stats)
|
||||||
|
|
||||||
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
||||||
@@ -22,6 +23,9 @@ end
|
|||||||
symbols.__index = symbols
|
symbols.__index = symbols
|
||||||
setmetatable(M, symbols)
|
setmetatable(M, symbols)
|
||||||
|
|
||||||
|
local id_ = 0
|
||||||
|
local id = function() id_=id_+1 return id_ end M.id=id
|
||||||
|
|
||||||
M.link = function()
|
M.link = function()
|
||||||
if stats.unused then return end
|
if stats.unused then return end
|
||||||
|
|
||||||
@@ -34,79 +38,28 @@ M.link = function()
|
|||||||
return val
|
return val
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for _,location in ipairs(locations) do
|
for _,section in ipairs(sections) do
|
||||||
for _,section in ipairs(location.sections) do
|
|
||||||
section:compute_size()
|
section:compute_size()
|
||||||
end
|
end
|
||||||
end
|
|
||||||
symbols.__index = symbols
|
symbols.__index = symbols
|
||||||
|
|
||||||
stats.used = 0
|
local chunk_reserve = function(chunks, chunk_ix, chunk, start, size)
|
||||||
stats.unused = 0
|
|
||||||
stats.cycles = 0
|
|
||||||
for _,location in ipairs(locations) do
|
|
||||||
local sections,rorg = location.sections,location.rorg
|
|
||||||
|
|
||||||
local chunk_reserve = function(chunk_ix, chunk, start, size)
|
|
||||||
if start == chunk.start then
|
if start == chunk.start then
|
||||||
if size == chunk.size then location.chunks[chunk_ix] = nil
|
if size == chunk.size then chunks[chunk_ix] = nil
|
||||||
else chunk.start=start+size chunk.size=chunk.size-size end
|
else chunk.start=start+size chunk.size=chunk.size-size end
|
||||||
else
|
else
|
||||||
if chunk.size - (start - chunk.start) == size then chunk.size = chunk.size - size
|
if chunk.size - (start - chunk.start) == size then chunk.size = chunk.size - size
|
||||||
else
|
else
|
||||||
local sz = start - chunk.start
|
local sz = start - chunk.start
|
||||||
table.insert(location.chunks, chunk_ix+1, { start=start+size, size=chunk.size-(sz+size) })
|
table.insert(chunks, chunk_ix+1, { start=start+size, size=chunk.size-(sz+size) })
|
||||||
chunk.size = sz
|
chunk.size = sz
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- filter sections list
|
local position_section = function(section, constrain)
|
||||||
local position_independent_sections = {}
|
local location = section.location
|
||||||
local symbols_to_remove = {}
|
local rorg = location.rorg
|
||||||
local section_count = #sections
|
|
||||||
location.cycles=0 location.used=0
|
|
||||||
for ix,section in ipairs(sections) do
|
|
||||||
location.cycles = location.cycles + section.cycles
|
|
||||||
location.used = location.used + section.size
|
|
||||||
if section.size == 0 then
|
|
||||||
sections[ix]=nil
|
|
||||||
if not section.org then table.insert(symbols_to_remove, section.label) end
|
|
||||||
elseif not section.org then
|
|
||||||
if M.strip and not section.refcount and not section.strong then
|
|
||||||
sections[ix]=nil
|
|
||||||
table.insert(symbols_to_remove, section.label)
|
|
||||||
else
|
|
||||||
table.insert(position_independent_sections, section)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
do local j=0 for i=1,section_count do
|
|
||||||
if sections[i] ~= nil then j=j+1 sections[j],sections[i] = sections[i],sections[j] end
|
|
||||||
end end
|
|
||||||
for _,v in ipairs(symbols_to_remove) do symbols[v] = nil end
|
|
||||||
stats.cycles = stats.cycles + location.cycles
|
|
||||||
stats.used = stats.used + location.used
|
|
||||||
|
|
||||||
-- fixed position sections
|
|
||||||
for section_ix,section in ipairs(sections) do if section.org then
|
|
||||||
if section.org < location.start or section.org > location.finish then
|
|
||||||
error("ORG section " .. section.label .. " starts outside container location")
|
|
||||||
end
|
|
||||||
for chunk_ix,chunk in ipairs(location.chunks) do
|
|
||||||
if chunk.start <= section.org and chunk.size - (section.org - chunk.start) >= section.size then
|
|
||||||
chunk_reserve(chunk_ix, chunk, section.org, section.size)
|
|
||||||
symbols[section.label] = rorg(section.org)
|
|
||||||
goto chunk_located
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("ORG section " .. section.label .. " overflows its location")
|
|
||||||
::chunk_located::
|
|
||||||
end end
|
|
||||||
|
|
||||||
-- position independent sections
|
|
||||||
table.sort(position_independent_sections, function(a,b) return a.size==b.size and a.label>b.label or a.size>b.size end)
|
|
||||||
for _,section in ipairs(position_independent_sections) do
|
|
||||||
local chunks = {}
|
local chunks = {}
|
||||||
for _,chunk in ipairs(location.chunks) do
|
for _,chunk in ipairs(location.chunks) do
|
||||||
if chunk.size >= section.size then chunks[#chunks+1] = chunk end
|
if chunk.size >= section.size then chunks[#chunks+1] = chunk end
|
||||||
@@ -155,6 +108,7 @@ M.link = function()
|
|||||||
if lsb_cur <= lsb_new then goto constraints_not_met end
|
if lsb_cur <= lsb_new then goto constraints_not_met end
|
||||||
end
|
end
|
||||||
::select_pos::
|
::select_pos::
|
||||||
|
if constrain and not constrain(address) then goto constraints_not_met end
|
||||||
waste=w position=address position_end=address_end
|
waste=w position=address position_end=address_end
|
||||||
::constraints_not_met::
|
::constraints_not_met::
|
||||||
end
|
end
|
||||||
@@ -166,16 +120,94 @@ M.link = function()
|
|||||||
usage_lowest(start, chunk.start + chunk.size - section.size)
|
usage_lowest(start, chunk.start + chunk.size - section.size)
|
||||||
end
|
end
|
||||||
if position then
|
if position then
|
||||||
chunk_reserve(chunk_ix, chunk, position, section.size)
|
chunk_reserve(location.chunks, chunk_ix, chunk, position, section.size)
|
||||||
section.org = position
|
section.org = position
|
||||||
symbols[section.label] = rorg(position)
|
symbols[section.label] = rorg(position)
|
||||||
--print(section.label, string.format("%04X\t%d", position, section.size))
|
--print(section.label, string.format("%04X\t%d", position, section.size))
|
||||||
--for k,v in ipairs(location.chunks) do print(string.format(" %04X %04X %d", v.start, v.size+v.start-1, v.size)) end
|
--for k,v in ipairs(location.chunks) do print(string.format(" %04X %04X %d", v.start, v.size+v.start-1, v.size)) end
|
||||||
|
return position
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local sibling_sections = {}
|
||||||
|
stats.used = 0
|
||||||
|
stats.unused = 0
|
||||||
|
stats.cycles = 0
|
||||||
|
for _,location in ipairs(locations) do
|
||||||
|
local sections,rorg = location.sections,location.rorg
|
||||||
|
|
||||||
|
-- filter sections list
|
||||||
|
local position_independent_sections = {}
|
||||||
|
local symbols_to_remove = {}
|
||||||
|
local section_count = #sections
|
||||||
|
location.cycles=0 location.used=0
|
||||||
|
for ix,section in ipairs(sections) do
|
||||||
|
location.cycles = location.cycles + section.cycles
|
||||||
|
location.used = location.used + section.size
|
||||||
|
if section.size == 0 then
|
||||||
|
sections[ix]=nil
|
||||||
|
if not section.org then table.insert(symbols_to_remove, section.label) end
|
||||||
|
elseif not section.org then
|
||||||
|
if M.strip and not section.refcount and not section.strong then
|
||||||
|
sections[ix]=nil
|
||||||
|
table.insert(symbols_to_remove, section.label)
|
||||||
|
elseif section.siblings then
|
||||||
|
table.insert(sibling_sections, section)
|
||||||
|
else
|
||||||
|
table.insert(position_independent_sections, section)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
do local j=0 for i=1,section_count do
|
||||||
|
if sections[i] ~= nil then j=j+1 sections[j],sections[i] = sections[i],sections[j] end
|
||||||
|
end end
|
||||||
|
for _,v in ipairs(symbols_to_remove) do symbols[v] = nil end
|
||||||
|
location.position_independent_sections = position_independent_sections
|
||||||
|
stats.cycles = stats.cycles + location.cycles
|
||||||
|
stats.used = stats.used + location.used
|
||||||
|
|
||||||
|
-- fixed position sections
|
||||||
|
for section_ix,section in ipairs(sections) do if section.org then
|
||||||
|
if section.org < location.start or section.org > location.finish then
|
||||||
|
error("ORG section " .. section.label .. " starts outside container location")
|
||||||
|
end
|
||||||
|
for chunk_ix,chunk in ipairs(location.chunks) do
|
||||||
|
if chunk.start <= section.org and chunk.size - (section.org - chunk.start) >= section.size then
|
||||||
|
chunk_reserve(location.chunks, chunk_ix, chunk, section.org, section.size)
|
||||||
|
symbols[section.label] = rorg(section.org)
|
||||||
goto chunk_located
|
goto chunk_located
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
error("unable to find space for section " .. section.label)
|
error("ORG section " .. section.label .. " overflows its location")
|
||||||
::chunk_located::
|
::chunk_located::
|
||||||
|
end end
|
||||||
|
end
|
||||||
|
--[[
|
||||||
|
for _,section in ipairs(sibling_sections) do
|
||||||
|
local sections = section.siblings
|
||||||
|
table.insert(sections, section)
|
||||||
|
-- biggest of all siblings first
|
||||||
|
table.sort(sections, function(a,b) return a.size==b.size and a.id<b.id or a.size>b.size end)
|
||||||
|
end
|
||||||
|
table.sort(sibling_sections, function(a,b) return a[1].size==b[1].size and a[1].id<b[1].id or a[1].size>b[1].size end)
|
||||||
|
for _,section in ipairs(sibling_sections) do
|
||||||
|
local siblings = section.siblings
|
||||||
|
local relate = section.relate or function(sibling, siblings)
|
||||||
|
end
|
||||||
|
for _,sibling in siblings do
|
||||||
|
if not relate(sibling, siblings) then goto not_suitable end
|
||||||
|
end
|
||||||
|
::not_suitable::
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
for _,location in ipairs(locations) do
|
||||||
|
local position_independent_sections = location.position_independent_sections
|
||||||
|
table.sort(position_independent_sections, function(a,b) return a.size==b.size and a.label>b.label or a.size>b.size end)
|
||||||
|
for _,section in ipairs(position_independent_sections) do
|
||||||
|
if not position_section(section) then
|
||||||
|
error("unable to find space for section " .. section.label)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- unused space stats
|
-- unused space stats
|
||||||
@@ -235,7 +267,6 @@ M.genbin = function(filler)
|
|||||||
for _,section in ipairs(sections) do
|
for _,section in ipairs(sections) do
|
||||||
assert(section.org >= #bin+of0)
|
assert(section.org >= #bin+of0)
|
||||||
for i=#bin+of0,section.org-1 do ins(bin, filler) end
|
for i=#bin+of0,section.org-1 do ins(bin, filler) end
|
||||||
M.label_current = section.label
|
|
||||||
for _,instruction in ipairs(section.instructions) do
|
for _,instruction in ipairs(section.instructions) do
|
||||||
local b,f = instruction.bin,instruction.asbin
|
local b,f = instruction.bin,instruction.asbin
|
||||||
if b then mov(b,1,#b,#bin+1,bin)
|
if b then mov(b,1,#b,#bin+1,bin)
|
||||||
@@ -323,7 +354,7 @@ M.location = function(start, finish)
|
|||||||
location.rorg = function(x) return x+offset end
|
location.rorg = function(x) return x+offset end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
location.sections = {}
|
location.sections = {} -- TODO remove
|
||||||
if not location.rorg then location.rorg = function(x) return x end end
|
if not location.rorg then location.rorg = function(x) return x end end
|
||||||
local size = (location.finish or math.huge) - location.start + 1
|
local size = (location.finish or math.huge) - location.start + 1
|
||||||
location.chunks={ { start=location.start, size=size } }
|
location.chunks={ { start=location.start, size=size } }
|
||||||
@@ -334,21 +365,22 @@ end
|
|||||||
|
|
||||||
M.section = function(t)
|
M.section = function(t)
|
||||||
local section = {}
|
local section = {}
|
||||||
if (type(t) == 'string') then section.label = t
|
local name = t or 'S'..id()
|
||||||
else
|
if (type(name) ~= 'string') then
|
||||||
assert(type(t) == 'table')
|
assert(type(t) == 'table', "invalid arguments for section")
|
||||||
assert(type(t[1]) == 'string' and string.len(t[1]) > 0)
|
assert(type(t[1]) == 'string' and string.len(t[1]) > 0, "invalid name for section")
|
||||||
section=t section.label=t[1] section[1]=nil
|
section=t name=t[1] section[1]=nil
|
||||||
if section.offset and not section.align then error("section " .. section.label .. " has offset, but no align") end
|
if section.offset and not section.align then error("section " .. name .. " has offset, but no align") end
|
||||||
end
|
end
|
||||||
table.insert(M.location_current.sections, section)
|
table.insert(M.location_current.sections, section) -- TODO remove
|
||||||
if symbols[section.label] then error("duplicate symbol: " .. section.label) end
|
table.insert(M.sections, section)
|
||||||
symbols[section.label] = section
|
section.location = M.location_current
|
||||||
M.label_current = section.label
|
|
||||||
M.section_current = section
|
M.section_current = section
|
||||||
section.type = 'section'
|
section.id = id()
|
||||||
section.constraints = {}
|
section.constraints = {}
|
||||||
section.instructions = {}
|
section.instructions = {}
|
||||||
|
assert(name:sub(1,1) ~= '_', "sections can't be named with a local label")
|
||||||
|
section.label = M.label(name)
|
||||||
function section:compute_size()
|
function section:compute_size()
|
||||||
local instructions = self.instructions
|
local instructions = self.instructions
|
||||||
self.size=0 self.cycles=0
|
self.size=0 self.cycles=0
|
||||||
@@ -373,12 +405,11 @@ M.section = function(t)
|
|||||||
return section
|
return section
|
||||||
end
|
end
|
||||||
|
|
||||||
M.label_gen_ix = 0
|
|
||||||
M.label = function(name)
|
M.label = function(name)
|
||||||
local label,offset
|
local label,offset
|
||||||
local section,rorg = M.section_current,M.location_current.rorg
|
local section,rorg = M.section_current,M.location_current.rorg
|
||||||
label = { type='label' }
|
label = { type='label', section=section }
|
||||||
if not name then name='_L'..M.label_gen_ix M.label_gen_ix=M.label_gen_ix+1 end
|
if not name then name='_L'..id() end
|
||||||
if name:sub(1,1) == '_' then -- local label
|
if name:sub(1,1) == '_' then -- local label
|
||||||
name = M.label_current .. name
|
name = M.label_current .. name
|
||||||
else
|
else
|
||||||
@@ -412,9 +443,18 @@ M.endpage = function()
|
|||||||
constraint.to = #section.instructions
|
constraint.to = #section.instructions
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M.sleep = function(cycles, noillegal)
|
||||||
|
assert(cycles > 1, "can't sleep for less than 2 cycles")
|
||||||
|
if cycles & 1 ~= 0 then
|
||||||
|
if noillegal then bitzpg(0) else nopzpg(0) end
|
||||||
|
cycles = cycles - 3
|
||||||
|
end
|
||||||
|
for i=1,cycles/2 do nopimp() end
|
||||||
|
end
|
||||||
|
|
||||||
local size_ref = function(v)
|
local size_ref = function(v)
|
||||||
if type(v) == 'string' then v=symbols[v] end
|
if type(v) == 'string' then v=symbols[v] end
|
||||||
if type(v) == 'table' and v.type == 'section' then v.refcount = 1 + (v.refcount or 0) end
|
if type(v) == 'table' and v.type == 'label' then v.section.refcount = 1 + (v.section.refcount or 0) end
|
||||||
end
|
end
|
||||||
local size_dc = function(v)
|
local size_dc = function(v)
|
||||||
if type(v) == 'function' then
|
if type(v) == 'function' then
|
||||||
|
15
samples/vcs0.l65
Normal file
15
samples/vcs0.l65
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
require'vcs'
|
||||||
|
mappers['2K']()
|
||||||
|
|
||||||
|
local kernel = function()
|
||||||
|
ldx#0xb0 @_loop sta WSYNC stx COLUBK dex bne _loop
|
||||||
|
end
|
||||||
|
|
||||||
|
@@main
|
||||||
|
init()
|
||||||
|
@_frame
|
||||||
|
overscan() vblank() screen(kernel) jmp _frame
|
||||||
|
|
||||||
|
writebin(filename..'.bin')
|
||||||
|
writesym(filename..'.sym')
|
||||||
|
print(stats)
|
194
vcs.l65
194
vcs.l65
@@ -84,45 +84,160 @@ do
|
|||||||
for k,v in pairs(vcs) do symbols[k] = v end
|
for k,v in pairs(vcs) do symbols[k] = v end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
NTSC = {
|
||||||
|
TIM_OVERSCAN = 38, -- TIM64T, 2432 cycles = 32 scanlines
|
||||||
|
TIM_VBLANK = 45, -- TIM64T, 2880 cycles = ~ 38 scanlines
|
||||||
|
TIM_KERNEL = 15, -- T1024T, 15360 cycles = ~202 scanlines
|
||||||
|
}
|
||||||
|
PAL = {
|
||||||
|
TIM_OVERSCAN = 50, -- TIM64T, 3200 cycles = ~ 42 scanlines
|
||||||
|
TIM_VBLANK = 61, -- TIM64T, 3904 cycles = ~ 51 scanlines
|
||||||
|
TIM_KERNEL = 17, -- T1024T, 17408 cycles = ~229 scanlines
|
||||||
|
}
|
||||||
|
TV = PAL
|
||||||
|
|
||||||
|
init = function() cld ldx#0 txa local l=label() dex tsx pha bne l end
|
||||||
|
wait = function() local l=label() lda INTIM bne l end
|
||||||
|
overscan_begin = function() sta WSYNC lda#2 sta VBLANK lda#TV.TIM_OVERSCAN sta TIM64T end
|
||||||
|
overscan_end = wait
|
||||||
|
overscan = function(f) overscan_begin() if f then f() end overscan_end() end
|
||||||
|
vblank_begin = function()
|
||||||
|
lda#0b1110 local l=label() sta WSYNC sta VSYNC lsr bne l
|
||||||
|
lda#2 sta VBLANK lda#TV.TIM_VBLANK sta TIM64T
|
||||||
|
end
|
||||||
|
vblank_end = function() wait() sta WSYNC sta VBLANK end
|
||||||
|
vblank = function(f) vblank_begin() if f then f() end vblank_end() end
|
||||||
|
screen_begin = function() lda#TV.TIM_KERNEL sta T1024T end
|
||||||
|
screen_end = wait
|
||||||
|
screen = function(f) screen_begin() if f then f() end screen_end() end
|
||||||
|
|
||||||
|
nusiz = {
|
||||||
|
MSL_SIZE_1 = 16*0,
|
||||||
|
MSL_SIZE_2 = 16*1,
|
||||||
|
MSL_SIZE_4 = 16*2,
|
||||||
|
MSL_SIZE_8 = 16*3,
|
||||||
|
ONE_COPY = 0,
|
||||||
|
TWO_COPIES_CLOSE = 1,
|
||||||
|
TWO_COPIES_MEDIUM = 2,
|
||||||
|
THREE_COPIES_CLOSE = 3,
|
||||||
|
TWO_COPIES_WIDE = 4,
|
||||||
|
DOUBLE_SIZED_PLAYER = 5,
|
||||||
|
THREE_COPIES_MEDIUM = 6,
|
||||||
|
QUAD_SIZED_PLAYER = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrlpf = {
|
||||||
|
BALL_SIZE_1 = 16*0,
|
||||||
|
BALL_SIZE_2 = 16*1,
|
||||||
|
BALL_SIZE_4 = 16*2,
|
||||||
|
BALL_SIZE_8 = 16*3,
|
||||||
|
PF_MIRRORED = 1,
|
||||||
|
PF_SCOREMODE = 2,
|
||||||
|
PF_PRIO_BALLABOVE = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
enable = {
|
||||||
|
DISABLE = 0,
|
||||||
|
ENABLE = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
vdel = {
|
||||||
|
DISABLE = 0,
|
||||||
|
ENABLE = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
hm = {
|
||||||
|
LEFT_7 = 7*16,
|
||||||
|
LEFT_6 = 6*16,
|
||||||
|
LEFT_5 = 5*16,
|
||||||
|
LEFT_4 = 4*16,
|
||||||
|
LEFT_3 = 3*16,
|
||||||
|
LEFT_2 = 2*16,
|
||||||
|
LEFT_1 = 1*16,
|
||||||
|
NO_MOTION = 0,
|
||||||
|
RIGHT_1 = 15*16,
|
||||||
|
RIGHT_2 = 14*16,
|
||||||
|
RIGHT_3 = 13*16,
|
||||||
|
RIGHT_4 = 12*16,
|
||||||
|
RIGHT_5 = 11*16,
|
||||||
|
RIGHT_6 = 10*16,
|
||||||
|
RIGHT_7 = 9*16,
|
||||||
|
RIGHT_8 = 8*16,
|
||||||
|
|
||||||
|
C74_LEFT_15 = 7*16,
|
||||||
|
C74_LEFT_14 = 6*16,
|
||||||
|
C74_LEFT_13 = 5*16,
|
||||||
|
C74_LEFT_12 = 4*16,
|
||||||
|
C74_LEFT_11 = 3*16,
|
||||||
|
C74_LEFT_10 = 2*16,
|
||||||
|
C74_LEFT_9 = 1*16,
|
||||||
|
C74_LEFT_8 = 0*16,
|
||||||
|
C74_LEFT_7 = 15*16,
|
||||||
|
C74_LEFT_6 = 14*16,
|
||||||
|
C74_LEFT_5 = 13*16,
|
||||||
|
C74_LEFT_4 = 12*16,
|
||||||
|
C74_LEFT_3 = 11*16,
|
||||||
|
C74_LEFT_2 = 10*16,
|
||||||
|
C74_LEFT_1 = 9*16,
|
||||||
|
C74_NO_MOTION = 8*16,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- for mappers that swap banks in place
|
||||||
|
-- call an asm function into another bank and generate the stubs if needed
|
||||||
|
local far_stubs = {} M.far_stubs=far_stubs
|
||||||
|
local far = function(dst)
|
||||||
|
local stub,loc_src,loc_dst = far_stubs[dst],location_current,dst.section.location
|
||||||
|
if not (stub and stub.stub_caller.location==loc_src and stub.stub_callee.location==loc_dst) then
|
||||||
|
local seccur = section_current
|
||||||
|
local stub_caller = section() switchrom(loc_dst.rom) skip(6) rts
|
||||||
|
location(loc_dst)
|
||||||
|
local stub_callee = section() jsr dst switchrom(loc_src.rom)
|
||||||
|
location(loc_src) section_current=seccur
|
||||||
|
far_stubs[dst] = relate(stub_caller, stub_callee, 3)
|
||||||
|
end
|
||||||
|
jsr stub_caller
|
||||||
|
end
|
||||||
|
|
||||||
mappers = {}
|
mappers = {}
|
||||||
|
|
||||||
mappers['2K'] = function()
|
mappers['2K'] = function(irq)
|
||||||
rom0 = location(0xf800, 0xffff)
|
rom0 = location(0xf800, 0xffff)
|
||||||
section{"vectors", org=0xfffc} word(main,main)
|
section{"vectors", org=0xfffc} dc.w main if irq then dc.w main end
|
||||||
end
|
end
|
||||||
mappers.CV = mappers['2K']
|
mappers.CV = mappers['2K']
|
||||||
|
|
||||||
mappers['4K'] = function()
|
mappers['4K'] = function(irq)
|
||||||
rom0 = location(0xf000, 0xffff)
|
rom0 = location(0xf000, 0xffff)
|
||||||
section{"vectors", org=0xfffc} word(main,main)
|
section{"vectors", org=0xfffc} dc.w main if irq then dc.w main end
|
||||||
end
|
end
|
||||||
|
|
||||||
local bank_stubs = function(count, hotspot, entry)
|
local bank_stubs = function(irq, count, hotspot, entry)
|
||||||
function switchrom(i) assert(i>=0 and i<count) bit 0x1000+hotspot+i end
|
function switchrom(i) assert(i>=0 and i<count) bit 0x1000+hotspot+i end
|
||||||
|
far = far
|
||||||
local base = 0x10000 - (count << 12)
|
local base = 0x10000 - (count << 12)
|
||||||
for bi=0,count-1 do
|
for bi=0,count-1 do
|
||||||
local o = base+(bi<<12)
|
local o = base+(bi<<12)
|
||||||
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000, rom=bi}
|
||||||
local start=section{"entry"..bi, org=o+(entry or hotspot-6)} switchrom(0) if bi==0 then jmp main end
|
local start=section{"entry"..bi, org=o+(entry or hotspot-6)} switchrom(0) if bi==0 then jmp main end
|
||||||
section{"switchtab"..bi, org=o+hotspot} for i=1,count do byte(0) end
|
section{"switchtab"..bi, org=o+hotspot} for i=1,count do byte(0) end
|
||||||
section{"vectors"..bi, org=o+0xffc} word(start,start)
|
section{"vectors"..bi, org=o+0xffc} dc.w start if irq then dc.w start end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
mappers.FA = function() bank_stubs(3, 0xff8) end
|
mappers.FA = function(irq) bank_stubs(irq, 3, 0xff8) end
|
||||||
mappers.F8 = function() bank_stubs(2, 0xff8) end
|
mappers.F8 = function(irq) bank_stubs(irq, 2, 0xff8) end
|
||||||
mappers.F6 = function() bank_stubs(4, 0xff6) end
|
mappers.F6 = function(irq) bank_stubs(irq, 4, 0xff6) end
|
||||||
mappers.F4 = function() bank_stubs(8, 0xff4) end
|
mappers.F4 = function(irq) bank_stubs(irq, 8, 0xff4) end
|
||||||
mappers.EF = function() bank_stubs(16, 0xfe0, 0xffc-6) end
|
mappers.EF = function(irq) bank_stubs(irq, 16, 0xfe0, 0xffc-6) end
|
||||||
|
|
||||||
mappers.FE = function()
|
mappers.FE = function(irq)
|
||||||
rom0 = location(0xd000, 0xdfff)
|
rom1 = location(0xd000, 0xdfff)
|
||||||
section{"vectors0", org=0xdffc} word(main,main)
|
section{"vectors1", org=0xdffc} dc.w main if irq then dc.w main end
|
||||||
location{0xe000, 0xefff, nofill=true}
|
location{0xe000, 0xefff, nofill=true}
|
||||||
rom1 = location(0xf000, 0xffff)
|
rom0 = location(0xf000, 0xffff)
|
||||||
section{"vectors1", org=0xfffc} word(main,main)
|
section{"vectors0", org=0xfffc} dc.w main if irq then dc.w main end
|
||||||
end
|
end
|
||||||
|
|
||||||
mappers.E0 = function(map)
|
mappers.E0 = function(map, irq)
|
||||||
function switchrom0(i) assert(map[i]==0) bit 0x1fe0+i end
|
function switchrom0(i) assert(map[i]==0) bit 0x1fe0+i end
|
||||||
function switchrom1(i) assert(map[i]==1) bit 0x1fe8+i end
|
function switchrom1(i) assert(map[i]==1) bit 0x1fe8+i end
|
||||||
function switchrom2(i) assert(map[i]==2) bit 0x1ff0+i end
|
function switchrom2(i) assert(map[i]==2) bit 0x1ff0+i end
|
||||||
@@ -132,12 +247,12 @@ mappers.E0 = function(map)
|
|||||||
_ENV["rom"..bi] = location{0xe000+o, 0xe3ff+o, rorg=0xf000+map[bi]*0x400}
|
_ENV["rom"..bi] = location{0xe000+o, 0xe3ff+o, rorg=0xf000+map[bi]*0x400}
|
||||||
end
|
end
|
||||||
section{"switchtab", org=0xffe0} for i=1,8*3 do byte(0) end
|
section{"switchtab", org=0xffe0} for i=1,8*3 do byte(0) end
|
||||||
section{"vectors", org=0xfffc} word(main,main)
|
section{"vectors", org=0xfffc} dc.w main if irq then dc.w main end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- rom0 refers to the last one in ROM, ie the one always mapped to 0xF800-0xFFFF,
|
-- rom0 refers to the last one in ROM, ie the one always mapped to 0xF800-0xFFFF,
|
||||||
-- such that changing the rom count does not change its index
|
-- such that changing the rom count does not change its index
|
||||||
mappers['3F'] = function(count)
|
mappers['3F'] = function(count, irq)
|
||||||
function switchrom(i) assert(i>=0 and i<count-1) lda#i sta 0x3f end
|
function switchrom(i) assert(i>=0 and i<count-1) lda#i sta 0x3f end
|
||||||
local symbols=cpu.symbols for k,v in pairs(vcs) do -- remap TIA to 0x40-0x7F
|
local symbols=cpu.symbols for k,v in pairs(vcs) do -- remap TIA to 0x40-0x7F
|
||||||
if v<0x40 then v=v+0x40 vcs[k]=v symbols[k]=v end
|
if v<0x40 then v=v+0x40 vcs[k]=v symbols[k]=v end
|
||||||
@@ -148,10 +263,10 @@ mappers['3F'] = function(count)
|
|||||||
end
|
end
|
||||||
local o = 0x800 * (count-1) + 0x10000
|
local o = 0x800 * (count-1) + 0x10000
|
||||||
rom0 = location{o, 0x7ff+o, rorg=0xf800}
|
rom0 = location{o, 0x7ff+o, rorg=0xf800}
|
||||||
section{"vectors", org=0xfffc} word(main,main)
|
section{"vectors", org=0xfffc} dc.w main if irq then dc.w main end
|
||||||
end
|
end
|
||||||
|
|
||||||
mappers.E7 = function()
|
mappers.E7 = function(irq)
|
||||||
function switchrom(i) assert(i>=0 and i<7) bit 0x1fe0+i end
|
function switchrom(i) assert(i>=0 and i<7) bit 0x1fe0+i end
|
||||||
function enableram() bit 0x1fe7 end
|
function enableram() bit 0x1fe7 end
|
||||||
function switchram(i) assert(i>=0 and i<4) bit 0x1fe8+i end
|
function switchram(i) assert(i>=0 and i<4) bit 0x1fe8+i end
|
||||||
@@ -161,56 +276,58 @@ mappers.E7 = function()
|
|||||||
end
|
end
|
||||||
rom7 = location{0xf800, 0xffff, rorg=0xf800}
|
rom7 = location{0xf800, 0xffff, rorg=0xf800}
|
||||||
section{"switchtab", org=0xffe0} for i=1,12 do byte(0) end
|
section{"switchtab", org=0xffe0} for i=1,12 do byte(0) end
|
||||||
section{"vectors", org=0xfffc} word(main,main)
|
section{"vectors", org=0xfffc} dc.w main if irq then dc.w main end
|
||||||
end
|
end
|
||||||
|
|
||||||
mappers.F0 = function()
|
mappers.F0 = function(irq)
|
||||||
function switchrom() lda 0x1ff0 end
|
function switchrom() lda 0x1ff0 end
|
||||||
for bi=0,15 do
|
for bi=0,15 do
|
||||||
local o = bi*0x1000 + 0x1000
|
local o = bi*0x1000 + 0x1000
|
||||||
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
||||||
local start=section{"entry"..bi, org=o+0xffc-8}
|
local start=section{"entry"..bi, org=o+0xffc-8}
|
||||||
@_loop switchrom() bne _loop
|
local l=label() switchrom() bne l
|
||||||
if bi==0 then jmp main end
|
if bi==0 then jmp main end
|
||||||
section{"switchtab"..bi, org=o+0xff0} byte(bi)
|
section{"switchtab"..bi, org=o+0xff0} byte(bi)
|
||||||
section{"vectors"..bi, org=o+0xffc} word(start,start)
|
section{"vectors"..bi, org=o+0xffc} dc.w start if irq then dc.w start end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local bank_stubs2 = function(hotspot0, hotspot1)
|
local bank_stubs2 = function(irq, hotspot0, hotspot1)
|
||||||
function switchrom(i)
|
function switchrom(i)
|
||||||
if i==0 then bit hotspot0
|
if i==0 then bit hotspot0
|
||||||
elseif i==1 then bit hotspot1
|
elseif i==1 then bit hotspot1
|
||||||
else error("invalid rom index: " .. i) end
|
else error("invalid rom index: " .. i) end
|
||||||
end
|
end
|
||||||
|
far = far
|
||||||
local base = 0xe000
|
local base = 0xe000
|
||||||
for bi=0,1 do
|
for bi=0,1 do
|
||||||
local o = base+(bi<<12)
|
local o = base+(bi<<12)
|
||||||
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
||||||
local start=section{"entry"..bi, org=o+0xffc-6} switchrom(0) if bi==0 then jmp main end
|
local start=section{"entry"..bi, org=o+0xffc-6} switchrom(0) if bi==0 then jmp main end
|
||||||
section{"vectors"..bi, org=o+0xffc} word(start,start)
|
section{"vectors"..bi, org=o+0xffc} dc.w start if irq then dc.w start end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
mappers.UA = function() bank_stubs2(0x220, 0x240) end
|
mappers.UA = function(irq) bank_stubs2(irq, 0x220, 0x240) end
|
||||||
mappers['0840'] = function() bank_stubs2(0x800, 0x840) end
|
mappers['0840'] = function(irq) bank_stubs2(irq, 0x800, 0x840) end
|
||||||
mappers.SB = function(count)
|
mappers.SB = function(count, irq)
|
||||||
function switchrom(i) assert(i>=0 and i<count) bit 0x800+i end
|
function switchrom(i) assert(i>=0 and i<count) bit 0x800+i end
|
||||||
|
far = far
|
||||||
for bi=0,count-1 do
|
for bi=0,count-1 do
|
||||||
local o = bi*0x1000 + 0x1000
|
local o = bi*0x1000 + 0x1000
|
||||||
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
||||||
local start=section{"entry"..bi, org=o+0xffc-6} switchrom(0) if bi==0 then jmp main end
|
local start=section{"entry"..bi, org=o+0xffc-6} switchrom(0) if bi==0 then jmp main end
|
||||||
section{"vectors"..bi, org=o+0xffc} word(start,start)
|
section{"vectors"..bi, org=o+0xffc} dc.w start if irq then dc.w start end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mappers['3E'] = function(rom_count, ram_count)
|
mappers['3E'] = function(rom_count, ram_count, irq)
|
||||||
mappers['3F'](rom_count)
|
mappers['3F'](rom_count, irq)
|
||||||
function switchram(i) assert(i>=0 and i<ram_count-1) lda#i sta 0x3E end
|
function switchram(i) assert(i>=0 and i<ram_count-1) lda#i sta 0x3E end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- rom0 refers to the last 1k in ROM, which is mapped automatically on reset,
|
-- rom0 refers to the last 1k in ROM, which is mapped automatically on reset,
|
||||||
-- such that changing the rom count does not change its index
|
-- such that changing the rom count does not change its index
|
||||||
mappers.MC = function(rom_count, ram_count)
|
mappers.MC = function(rom_count, ram_count, irq)
|
||||||
for i=0,3 do
|
for i=0,3 do
|
||||||
_ENV['switchrom'..i] = function(i) assert(i>=0 and i<128) lda#i sta 0x3c+i end
|
_ENV['switchrom'..i] = function(i) assert(i>=0 and i<128) lda#i sta 0x3c+i end
|
||||||
_ENV['switchram'..i] = function(i) assert(i>=0 and i<128) lda#i+0x80 sta 0x3c+i end
|
_ENV['switchram'..i] = function(i) assert(i>=0 and i<128) lda#i+0x80 sta 0x3c+i end
|
||||||
@@ -220,17 +337,18 @@ mappers.MC = function(rom_count, ram_count)
|
|||||||
_ENV["rom"..(count-1-bi)] = location{o, 0x3ff+o, rorg=0xf000+(o&0xfff)}
|
_ENV["rom"..(count-1-bi)] = location{o, 0x3ff+o, rorg=0xf000+(o&0xfff)}
|
||||||
end
|
end
|
||||||
local start=section("entry") switchrom3(0) jmp main
|
local start=section("entry") switchrom3(0) jmp main
|
||||||
section{"vectors", org=0xfffc} word(start,start)
|
section{"vectors", org=0xfffc} dc.w start if irq then dc.w start end
|
||||||
end
|
end
|
||||||
|
|
||||||
mappers.X07 = function()
|
mappers.X07 = function(irq)
|
||||||
function switchrom(i) assert(i>=0 and i<16) bit 0x80b+(i<<4) end
|
function switchrom(i) assert(i>=0 and i<16) bit 0x80b+(i<<4) end
|
||||||
|
far = far
|
||||||
-- map TIA also to 0x40-0x7F: use VSYNC for bank 14, and VSYNC2 for bank 15
|
-- map TIA also to 0x40-0x7F: use VSYNC for bank 14, and VSYNC2 for bank 15
|
||||||
vcs.VSYNC2=0x40 cpu.symbols.VSYNC2=0x40
|
vcs.VSYNC2=0x40 cpu.symbols.VSYNC2=0x40
|
||||||
for bi=0,count-1 do
|
for bi=0,count-1 do
|
||||||
local o = bi*0x1000 + 0x1000
|
local o = bi*0x1000 + 0x1000
|
||||||
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
||||||
local start=section{"entry"..bi, org=o+0xffc-6} switchrom(0) if bi==0 then jmp main end
|
local start=section{"entry"..bi, org=o+0xffc-6} switchrom(0) if bi==0 then jmp main end
|
||||||
section{"vectors"..bi, org=o+0xffc} word(start,start)
|
section{"vectors"..bi, org=o+0xffc} dc.w start if irq then dc.w start end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user