mirror of
https://github.com/g012/l65.git
synced 2024-12-29 16:29:15 +00:00
Sections now generate regular labels for themselves.
This commit is contained in:
parent
a400eb145e
commit
71e6f35a3c
194
6502.lua
194
6502.lua
@ -2,6 +2,7 @@ local M = {}
|
||||
|
||||
local symbols={} M.symbols=symbols
|
||||
local locations={} M.locations=locations
|
||||
local sections={} M.sections=sections
|
||||
local stats={} M.stats=stats setmetatable(stats, stats)
|
||||
|
||||
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
||||
@ -22,6 +23,9 @@ end
|
||||
symbols.__index = symbols
|
||||
setmetatable(M, symbols)
|
||||
|
||||
local id_ = 0
|
||||
local id = function() id_=id_+1 return id_ end M.id=id
|
||||
|
||||
M.link = function()
|
||||
if stats.unused then return end
|
||||
|
||||
@ -34,79 +38,28 @@ M.link = function()
|
||||
return val
|
||||
end
|
||||
end
|
||||
for _,location in ipairs(locations) do
|
||||
for _,section in ipairs(location.sections) do
|
||||
for _,section in ipairs(sections) do
|
||||
section:compute_size()
|
||||
end
|
||||
end
|
||||
symbols.__index = symbols
|
||||
|
||||
stats.used = 0
|
||||
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)
|
||||
local chunk_reserve = function(chunks, chunk_ix, chunk, start, size)
|
||||
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
|
||||
if chunk.size - (start - chunk.start) == size then chunk.size = chunk.size - size
|
||||
else
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 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)
|
||||
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 position_section = function(section, constrain)
|
||||
local location = section.location
|
||||
local rorg = location.rorg
|
||||
local chunks = {}
|
||||
for _,chunk in ipairs(location.chunks) do
|
||||
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
|
||||
end
|
||||
::select_pos::
|
||||
if constrain and not constrain(address) then goto constraints_not_met end
|
||||
waste=w position=address position_end=address_end
|
||||
::constraints_not_met::
|
||||
end
|
||||
@ -166,16 +120,94 @@ M.link = function()
|
||||
usage_lowest(start, chunk.start + chunk.size - section.size)
|
||||
end
|
||||
if position then
|
||||
chunk_reserve(chunk_ix, chunk, position, section.size)
|
||||
chunk_reserve(location.chunks, chunk_ix, chunk, position, section.size)
|
||||
section.org = position
|
||||
symbols[section.label] = rorg(position)
|
||||
--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
|
||||
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
|
||||
end
|
||||
end
|
||||
error("unable to find space for section " .. section.label)
|
||||
error("ORG section " .. section.label .. " overflows its location")
|
||||
::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
|
||||
|
||||
-- unused space stats
|
||||
@ -235,7 +267,6 @@ M.genbin = function(filler)
|
||||
for _,section in ipairs(sections) do
|
||||
assert(section.org >= #bin+of0)
|
||||
for i=#bin+of0,section.org-1 do ins(bin, filler) end
|
||||
M.label_current = section.label
|
||||
for _,instruction in ipairs(section.instructions) do
|
||||
local b,f = instruction.bin,instruction.asbin
|
||||
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
|
||||
end
|
||||
end
|
||||
location.sections = {}
|
||||
location.sections = {} -- TODO remove
|
||||
if not location.rorg then location.rorg = function(x) return x end end
|
||||
local size = (location.finish or math.huge) - location.start + 1
|
||||
location.chunks={ { start=location.start, size=size } }
|
||||
@ -334,21 +365,22 @@ end
|
||||
|
||||
M.section = function(t)
|
||||
local section = {}
|
||||
if (type(t) == 'string') then section.label = t
|
||||
else
|
||||
assert(type(t) == 'table')
|
||||
assert(type(t[1]) == 'string' and string.len(t[1]) > 0)
|
||||
section=t section.label=t[1] section[1]=nil
|
||||
if section.offset and not section.align then error("section " .. section.label .. " has offset, but no align") end
|
||||
local name = t or 'S'..id()
|
||||
if (type(name) ~= 'string') then
|
||||
assert(type(t) == 'table', "invalid arguments for section")
|
||||
assert(type(t[1]) == 'string' and string.len(t[1]) > 0, "invalid name for section")
|
||||
section=t name=t[1] section[1]=nil
|
||||
if section.offset and not section.align then error("section " .. name .. " has offset, but no align") end
|
||||
end
|
||||
table.insert(M.location_current.sections, section)
|
||||
if symbols[section.label] then error("duplicate symbol: " .. section.label) end
|
||||
symbols[section.label] = section
|
||||
M.label_current = section.label
|
||||
table.insert(M.location_current.sections, section) -- TODO remove
|
||||
table.insert(M.sections, section)
|
||||
section.location = M.location_current
|
||||
M.section_current = section
|
||||
section.type = 'section'
|
||||
section.id = id()
|
||||
section.constraints = {}
|
||||
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()
|
||||
local instructions = self.instructions
|
||||
self.size=0 self.cycles=0
|
||||
@ -373,12 +405,11 @@ M.section = function(t)
|
||||
return section
|
||||
end
|
||||
|
||||
M.label_gen_ix = 0
|
||||
M.label = function(name)
|
||||
local label,offset
|
||||
local section,rorg = M.section_current,M.location_current.rorg
|
||||
label = { type='label' }
|
||||
if not name then name='_L'..M.label_gen_ix M.label_gen_ix=M.label_gen_ix+1 end
|
||||
label = { type='label', section=section }
|
||||
if not name then name='_L'..id() end
|
||||
if name:sub(1,1) == '_' then -- local label
|
||||
name = M.label_current .. name
|
||||
else
|
||||
@ -412,9 +443,18 @@ M.endpage = function()
|
||||
constraint.to = #section.instructions
|
||||
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)
|
||||
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
|
||||
local size_dc = function(v)
|
||||
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
|
||||
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['2K'] = function()
|
||||
mappers['2K'] = function(irq)
|
||||
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
|
||||
mappers.CV = mappers['2K']
|
||||
|
||||
mappers['4K'] = function()
|
||||
mappers['4K'] = function(irq)
|
||||
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
|
||||
|
||||
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
|
||||
far = far
|
||||
local base = 0x10000 - (count << 12)
|
||||
for bi=0,count-1 do
|
||||
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
|
||||
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
|
||||
mappers.FA = function() bank_stubs(3, 0xff8) end
|
||||
mappers.F8 = function() bank_stubs(2, 0xff8) end
|
||||
mappers.F6 = function() bank_stubs(4, 0xff6) end
|
||||
mappers.F4 = function() bank_stubs(8, 0xff4) end
|
||||
mappers.EF = function() bank_stubs(16, 0xfe0, 0xffc-6) end
|
||||
mappers.FA = function(irq) bank_stubs(irq, 3, 0xff8) end
|
||||
mappers.F8 = function(irq) bank_stubs(irq, 2, 0xff8) end
|
||||
mappers.F6 = function(irq) bank_stubs(irq, 4, 0xff6) end
|
||||
mappers.F4 = function(irq) bank_stubs(irq, 8, 0xff4) end
|
||||
mappers.EF = function(irq) bank_stubs(irq, 16, 0xfe0, 0xffc-6) end
|
||||
|
||||
mappers.FE = function()
|
||||
rom0 = location(0xd000, 0xdfff)
|
||||
section{"vectors0", org=0xdffc} word(main,main)
|
||||
mappers.FE = function(irq)
|
||||
rom1 = location(0xd000, 0xdfff)
|
||||
section{"vectors1", org=0xdffc} dc.w main if irq then dc.w main end
|
||||
location{0xe000, 0xefff, nofill=true}
|
||||
rom1 = location(0xf000, 0xffff)
|
||||
section{"vectors1", org=0xfffc} word(main,main)
|
||||
rom0 = location(0xf000, 0xffff)
|
||||
section{"vectors0", org=0xfffc} dc.w main if irq then dc.w main end
|
||||
end
|
||||
|
||||
mappers.E0 = function(map)
|
||||
mappers.E0 = function(map, irq)
|
||||
function switchrom0(i) assert(map[i]==0) bit 0x1fe0+i end
|
||||
function switchrom1(i) assert(map[i]==1) bit 0x1fe8+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}
|
||||
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
|
||||
|
||||
-- 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
|
||||
mappers['3F'] = function(count)
|
||||
mappers['3F'] = function(count, irq)
|
||||
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
|
||||
if v<0x40 then v=v+0x40 vcs[k]=v symbols[k]=v end
|
||||
@ -148,10 +263,10 @@ mappers['3F'] = function(count)
|
||||
end
|
||||
local o = 0x800 * (count-1) + 0x10000
|
||||
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
|
||||
|
||||
mappers.E7 = function()
|
||||
mappers.E7 = function(irq)
|
||||
function switchrom(i) assert(i>=0 and i<7) bit 0x1fe0+i end
|
||||
function enableram() bit 0x1fe7 end
|
||||
function switchram(i) assert(i>=0 and i<4) bit 0x1fe8+i end
|
||||
@ -161,56 +276,58 @@ mappers.E7 = function()
|
||||
end
|
||||
rom7 = location{0xf800, 0xffff, rorg=0xf800}
|
||||
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
|
||||
|
||||
mappers.F0 = function()
|
||||
mappers.F0 = function(irq)
|
||||
function switchrom() lda 0x1ff0 end
|
||||
for bi=0,15 do
|
||||
local o = bi*0x1000 + 0x1000
|
||||
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
|
||||
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
|
||||
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
|
||||
|
||||
local bank_stubs2 = function(hotspot0, hotspot1)
|
||||
local bank_stubs2 = function(irq, hotspot0, hotspot1)
|
||||
function switchrom(i)
|
||||
if i==0 then bit hotspot0
|
||||
elseif i==1 then bit hotspot1
|
||||
else error("invalid rom index: " .. i) end
|
||||
end
|
||||
far = far
|
||||
local base = 0xe000
|
||||
for bi=0,1 do
|
||||
local o = base+(bi<<12)
|
||||
_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
|
||||
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
|
||||
mappers.UA = function() bank_stubs2(0x220, 0x240) end
|
||||
mappers['0840'] = function() bank_stubs2(0x800, 0x840) end
|
||||
mappers.SB = function(count)
|
||||
mappers.UA = function(irq) bank_stubs2(irq, 0x220, 0x240) end
|
||||
mappers['0840'] = function(irq) bank_stubs2(irq, 0x800, 0x840) end
|
||||
mappers.SB = function(count, irq)
|
||||
function switchrom(i) assert(i>=0 and i<count) bit 0x800+i end
|
||||
far = far
|
||||
for bi=0,count-1 do
|
||||
local o = bi*0x1000 + 0x1000
|
||||
_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
|
||||
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
|
||||
|
||||
mappers['3E'] = function(rom_count, ram_count)
|
||||
mappers['3F'](rom_count)
|
||||
mappers['3E'] = function(rom_count, ram_count, irq)
|
||||
mappers['3F'](rom_count, irq)
|
||||
function switchram(i) assert(i>=0 and i<ram_count-1) lda#i sta 0x3E end
|
||||
end
|
||||
|
||||
-- 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
|
||||
mappers.MC = function(rom_count, ram_count)
|
||||
mappers.MC = function(rom_count, ram_count, irq)
|
||||
for i=0,3 do
|
||||
_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
|
||||
@ -220,17 +337,18 @@ mappers.MC = function(rom_count, ram_count)
|
||||
_ENV["rom"..(count-1-bi)] = location{o, 0x3ff+o, rorg=0xf000+(o&0xfff)}
|
||||
end
|
||||
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
|
||||
|
||||
mappers.X07 = function()
|
||||
mappers.X07 = function(irq)
|
||||
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
|
||||
vcs.VSYNC2=0x40 cpu.symbols.VSYNC2=0x40
|
||||
for bi=0,count-1 do
|
||||
local o = bi*0x1000 + 0x1000
|
||||
_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
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user