Good idea RB to check the m_80col to see if it is in 80 column mode.

Also if you want to see how drawing by rows works, just do a

drawbyrow(true)


Code

-- 80 column text overlay for Apple IIe

function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function striphi(a) if type(a)=="number" then a=string.char(a) end local b="" for i=1,#a do b=b..string.char(string.byte(a,i)&0x7f) end return b end

mem=manager:machine().devices[":maincpu"].spaces["program"]  -- gets main or aux, depending on softswitches
aux=emu.item(manager:machine().devices[":aux:ext80"].items["0/m_ram"])   -- gets aux memory
scr=manager:machine().screens[":screen"]
main=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])  -- always gets main memory

function widthpct(c) 
  if c==nil or c==string.char(0) then return 0 end 
  return ((manager:ui():get_string_width(c,1.0)/manager:ui():get_string_width("A",1.0))) 
end
function widthoffset(c) if c==nil or c==string.char(0) then return 0 end return 3.5*(1-widthpct(c)) end
-- assume chars have width of 7 pixels, center offset=7*((1-widthpercentage)/2)=3.5*(1-widthpercentage)

precalcwidthoffsettable={}

function precalccharwidthoffset()
  for i=0,255 do precalcwidthoffsettable[i]=widthoffset(string.char(i)) end
end

precalccharwidthoffset()

function widthoffsetpre(c)  if c==nil or c==string.char(0) then return 0 else return precalcwidthoffsettable[string.byte(c)] end end

function between(a,b,c) return (a >= b) and (a <= c) end
-- 80 column text overlay for Apple IIe

function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function striphi(a) if type(a)=="number" then a=string.char(a) end local b="" for i=1,#a do b=b..string.char(string.byte(a,i)&0x7f) end return b end

mem=manager:machine().devices[":maincpu"].spaces["program"]  -- gets main or aux, depending on softswitches
aux=emu.item(manager:machine().devices[":aux:ext80"].items["0/m_ram"])   -- gets aux memory
scr=manager:machine().screens[":screen"]
main=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])  -- always gets main memory

function widthpct(c) 
  if c==nil or c==string.char(0) then return 0 end 
  return ((manager:ui():get_string_width(c,1.0)/manager:ui():get_string_width("A",1.0))) 
end
function widthoffset(c) if c==nil or c==string.char(0) then return 0 end return 3.5*(1-widthpct(c)) end
-- assume chars have width of 7 pixels, center offset=7*((1-widthpercentage)/2)=3.5*(1-widthpercentage)

precalcwidthoffsettable={}

function precalccharwidthoffset()
  for i=0,255 do precalcwidthoffsettable[i]=widthoffset(string.char(i)) end
end

precalccharwidthoffset()

function widthoffsetpre(c)  if c==nil or c==string.char(0) then return 0 else return precalcwidthoffsettable[string.byte(c)] end end

function between(a,b,c) return (a >= b) and (a <= c) end

function applecharfixinverse(c)
  if type(c)=="string" then c=string.byte(c) end
  if between(c,0,31) then return string.char(c+64),true
  elseif between (c,32,127) then return string.char(c), true
  elseif between (c,128,159) then return string.char(c-128+64), false
  elseif between (c,160,255) then return string.char(c-128), false
  else return 0, false
  end
end

drawoverlay=true
keydelay=0

function print_80col()
for y=0,23 do for x=0,39 do offset=calc(y*8)-8192+x 
c1=striphi(aux:read(1024+offset)) c0=striphi(mem:read_u8(1024+offset)) 
io.write(c1..c0) end print() end
end

function interleavec1c0(c1row,c0row)
local outrow=""
for i=1,#c1row do
  outrow=outrow..applecharfixinverse(c1row:sub(i,i))..applecharfixinverse(c0row:sub(i,i))
end
return outrow
end

function draw_80colrow()
  if keydelay > 0 then keydelay = keydelay - 1 end
  local m_80col=emu.item(manager:machine().devices[":a2video"].items["0/m_80col"]):read(0)==1
  if drawoverlay then 
    scr:draw_box(0,0,559,279,0xff000000,0xffffffff)
    for y=0,23 do 
      offset=calc(y*8)-8192 
      c1row=aux:read_block(1024+offset,40)
      c0row=main:read_block(1024+offset,40)
      if m_80col then
        c0row=interleavec1c0(c1row,c0row)
      else
        c0row=interleavec1c0(string.rep(" ",40),c0row)
      end
      fgcolor,bgcolor=0xffffffff,0xff000000
      scr:draw_text(0,y*8,c0row,fgcolor,bgcolor) 
    end
  end
  if iskeypressed("KEYCODE_LSHIFT") and keydelay==0 then drawoverlay=not drawoverlay keydelay=20 end
end

m_80col_itemnum=-1

function draw_80col()
  if keydelay > 0 then keydelay = keydelay - 1 end
  -- might be a smidge faster if we didn't have to look up the itemnum for m_80col each time
  if m_80col_itemnum < 0 then m_80col_itemnum = manager:machine().devices[":a2video"].items["0/m_80col"] end
  local m_80col=emu.item(m_80col_itemnum):read(0)==1
  if drawoverlay then 
    scr:draw_box(0,0,559,279,0xff000000,0xffffffff)
    for y=0,23 do 
      offset=calc(y*8)-8192 
      c1row=aux:read_block(1024+offset,40)
      c0row=main:read_block(1024+offset,40)
      for x=0,39 do 
        c1=c1row:byte(x+1)
        c1,c1invert=applecharfixinverse(c1)
        c0=c0row:byte(x+1)
        c0,c0invert=applecharfixinverse(c0)
        fgcolor,bgcolor=0xffffffff,0xff000000
        if c1invert then fgcolor,bgcolor=bgcolor,fgcolor end
        --only draw the 80 columns if 80col is active
        if m_80col then
          scr:draw_text((x*2+0)*7+widthoffsetpre(c1),y*8,c1,fgcolor,bgcolor) 
        end
        fgcolor,bgcolor=0xffffffff,0xff000000
        if c0invert then fgcolor,bgcolor=bgcolor,fgcolor end
        scr:draw_text((x*2+1)*7+widthoffsetpre(c0),y*8,c0,fgcolor,bgcolor) 
      end 
    end
  end
  if iskeypressed("KEYCODE_LSHIFT") and keydelay==0 then drawoverlay=not drawoverlay keydelay=20 end
end

draw80dispatchlist={draw_80col}

function draw80dispatch() for i,j in pairs(draw80dispatchlist) do j() end end

function drawon() draw80dispatchlist={draw_80col} end
function drawoff() draw80dispatchlist={} end

-- Draw by rows by calling drawbyrow(true) or shut off with drawbyrow(false)
-- You end up losing the inverse chars and your ui font should be a monospace font
--  or it won't look right.  Also the fonts end up getting cropped at the right edge of the screen.
-- It's much faster since it can write out a whole 80 character row in one draw_text call
--  instead of 80 separate draw_text calls for each individual character.

function drawbyrow(a)
  if a==nil then a=true end
  if a==true then draw80dispatchlist={draw_80colrow} 
             else draw80dispatchlist={draw_80col}
  end
end

if not alreadyregistereddraw80 then
  emu.register_frame_done(draw80dispatch)
  alreadyregistereddraw80=true
end



Last edited by Golden Child; 03/04/19 09:27 PM. Reason: oops pasted some double text