Previous Thread
Next Thread
Print Thread
Page 11 of 80 1 2 9 10 11 12 13 79 80
Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
I figured out why using the debugger memory view to change the TMS9918 registers doesn't work.

so I try to set the TMS registers by hand with the debugger memory view, but it doesn't have any effect.

Because when you do it with the debugger memory view, it doesn't update the corresponding member variables. So not only do you have to set the m_Regs[x] variable, you also have to change the member variables.

In the file src/devices/video/tms9928.cpp when you write the registers with tms9928a_device::change_register, it updates other variables inside the driver, so for register 0, it will update m_color and m_pattern. Likewise for other registers.


Code
void tms9928a_device::change_register(uint8_t reg, uint8_t val)
{

...
		switch (reg)
	{
	case 0:
		/* re-calculate masks and pattern generator & colour */
		if (val & 2)
		{
			m_colour = ((m_Regs[3] & 0x80) * 64) & (m_vram_size - 1);
			m_pattern = ((m_Regs[4] & 4) * 2048) & (m_vram_size - 1);
			update_table_masks();
		}
		else
		{
			m_colour = (m_Regs[3] * 64) & (m_vram_size - 1);
			m_pattern = (m_Regs[4] * 2048) & (m_vram_size - 1);
		}
		m_mode = ( (m_reva ? (m_Regs[0] & 2) : 0) | ((m_Regs[1] & 0x10)>>4) | ((m_Regs[1] & 8)>>1));
		if ((val ^ prev) & 1)
			update_backdrop();
		if (TRACE_MODE) logerror("TMS9928A('%s'): %s\n", tag(), modes[m_mode]);
		break;


So I load my vram dump into the TMS.

The values to load into the registers are as follows:

Code
reginitarray = {2,194,14,255,3,63,3,1}; for index,val in pairs(reginitarray) do print(index-1,string.format("%x",val)) end
0	2
1	c2
2	e
3	ff
4	3
5	3f
6	3
7	1


so I set by hand with the debugger:

TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_Regs[0] to 2
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_Regs[1] to c2
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_pattern to 0 (address of the pattern table)
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_colour to 2000 (address of the color table)
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_nametbl to 3800 (address of the name table)
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_mode to 2 (graphics mode 2)

then I can see the bitmap display.

and if I further set:

TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_spritepattern to 1800
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_spriteattribute to 1f80

then I can see the sprites.

And if you want some weird effects, just set m_pattern to 1 to 7 (something you could never have on real hardware) or to 1800 (where the sprite patterns are).



I can see a table with the items in lua but it's just a list of items with the corresponding number.

Code
for i,j in pairs(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items) do print(i,j) end
1/0/m_start.seconds	610
0/0/m_start.seconds	605
0/m_clock_scale	439
0/m_Regs[6]	437
0/m_pattern	448
0/m_colour	441
0/m_colourmask	442
0/m_palette	446
0/m_patternmask	449
0/m_Regs[7]	440
0/m_spriteattribute	450
0/m_spritepattern	451
0/m_FifthSprite	428
0/m_nametbl	445
0/m_Regs[1]	432
0/m_Regs[0]	431
0/0/m_enabled	594
1/0/m_enabled	602
1/0/m_start.attoseconds	609
0/0/m_start.attoseconds	601
1/0/m_param	606
0/0/m_param	598
0/m_ReadAhead	429
0/m_Regs[2]	433
0/m_unscaled_clock	452
1/00000000-0000ffff	673
1/0/m_period.seconds	608
0/0/m_period.seconds	600
0/m_Regs[4]	435
0/m_StatusReg	444
0/m_INT	427
1/0/m_expire.attoseconds	603
0/m_latch	447
0/0/m_expire.seconds	596
1/0/m_expire.seconds	604
0/0/m_period.attoseconds	599
0/m_clock	438
0/0/m_expire.attoseconds	595
1/0/m_period.attoseconds	607
0/m_mode	443
0/m_Regs[5]	436
0/m_Addr	425
0/m_Regs[3]	434


I wish that I could read/write these items with lua in the same way that I can read/write them with the debugger memory view window.



Joined: Jan 2012
Posts: 891
Likes: 17
C
Senior Member
Offline
Senior Member
C
Joined: Jan 2012
Posts: 891
Likes: 17
try emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/0/m_start.seconds"]):read(offset) or :write(offset, newval) or :read_block(byte_offset, len).

Last edited by crazyc; 10/17/17 06:17 PM.
Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
Thank you, crazyc! That's exactly what I was looking for. Beauty!


Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
So with emu.item I can do this:

Code
dofile("../../arcbd_load_vram.lua")

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]):write(0,0)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_colour"]):write(0,0x2000)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_nametbl"]):write(0,0x3800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_mode"]):write(0,2)

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spritepattern"]):write(0,0x1800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spriteattribute"]):write(0,0x1f80)



There's a couple of other properties of emu.item that are interesting too, like .size and .count that are interesting to examine.

Item "0/m_pattern" has a size of 2 and count 1 while item "0/m_Regs[0]" has size of 1 and count 1.

Item "1/00000000-0000ffff" has a size of 1 and count 65536, and I can read/write into the vram with it.

Very cool. This lua engine is awesome!


Code
for i,j in pairs(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items) do print(i,j) end
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]).size)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]).count)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]).size)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]).count)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]).size)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]).count)

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):write(0,255)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):write(1,0xaa)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):write(2,0x55)

print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):read(0))
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):read(1))
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):read(2))


Joined: Jan 2012
Posts: 891
Likes: 17
C
Senior Member
Offline
Senior Member
C
Joined: Jan 2012
Posts: 891
Likes: 17
Right, size is the native byte width of an entry (like sizeof()) while count is number of size width words. If there are any other mame internals that you think would be useful to access from lua let me know. Also, if you haven't looked at the Scripty Things thead above, there's some neat stuff in there (and maybe post some of your stuff in it too).

Last edited by crazyc; 10/18/17 03:05 PM.
Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
Thanks again, CrazyC!

I am having such a blast fiddling with lua and mame. I haven't had this much fun programming for a long time.

I am still learning lua but it's so forgiving. And the console has auto-completion. Awesome! TAB for the win! This is pure genius.


I haven't quite figured out what the difference is between : and .

According to something I read, "The colon is for implementing methods that pass self as the first parameter. So x:bar(3,4) should be the same as x.bar(x,3,4)."


To start up the machine if you have the debugger active:
Code
manager:machine().devices[":maincpu"]:debug():go() 

And in trying to figure out the syntax I invariably interchange : with .

Code
print(manager:machine().devices[":maincpu"]:debug())
sol.device_debug*: 0x559857771518

but if I call the same thing, without the colon syntax, it blows with a segfault.

Code
print(manager:machine().devices[":maincpu"].debug())
Segmentation fault (core dumped)



The console plug in history is only 10 entries, but we can fix that easily by changing the line in plugins/console.init.lua
ln.historysetmaxlen(10) to something like 30.


Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
And one of the interesting things about older systems is that you often have to write your own routines to do graphics, like linedraws on the TMS9918. Drawing lines is actually pretty easy, just plot a pixel in the pattern memory by setting a bit, and set the color byte in the color memory.


[Linked Image from i.imgur.com]


Code
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]):write(0,0)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_colour"]):write(0,0x2000)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_nametbl"]):write(0,0x3800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_mode"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spritepattern"]):write(0,0x1800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spriteattribute"]):write(0,0x1f80)
--set background to 4
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[7]"]):write(0,0xf4)

mem=manager:machine().devices[":sl4:arcbd:arcbd_tms"].spaces["vram"]

function plotpixel(screenaddr,x,y)
local byteaddr = screenaddr + math.floor(y/8) * 256 + (y % 8) + math.floor(x/8) * 8
if x>=0 and x <=255 and y>=0 and y <=191 then
mem:write_u8(byteaddr,mem:read_u8(byteaddr)| (1 << (7-(x%8))))
end
end


function plotcolor(screenaddr,x,y,colorfg)
local byteaddr = screenaddr + math.floor(y/8) * 256 + (y % 8) + math.floor(x/8) * 8
if x>=0 and x<=255 and y>=0 and y<=191 then
--foreground single color
mem:write_u8(byteaddr,(mem:read_u8(byteaddr)& 0x0) | (math.floor(colorfg) << (4)) )
end
end


function deltasign(x)
if x<0 then return -1
elseif x==0 then return 0
elseif x>0 then return 1
else return 0
end
end


function linedraw(x1,y1,x2,y2,colorfg)
-- using basic code converted to lua from:
-- https://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm
--[[
 1500 REM === DRAW a LINE. Ported from C version
 1510 REM Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
 1520 DX = ABS(X2 - X1):SX = -1:IF X1 < X2 THEN SX = 1
 1530 DY = ABS(Y2 - Y1):SY = -1:IF Y1 < Y2 THEN SY = 1
 1540 ER = -DY:IF DX > DY THEN ER = DX
 1550 ER = INT(ER / 2)
 1560 PLOT X1,Y1:REM This command may differ depending ON BASIC dialect
 1570 IF X1 = X2 AND Y1 = Y2 THEN RETURN
 1580 E2 = ER
 1590 IF E2 > -DX THEN ER = ER - DY:X1 = X1 + SX
 1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY
 1610 GOTO 1560
--]]

x1 = math.floor(x1)
x2 = math.floor(x2)
y1 = math.floor(y1)
y2 = math.floor(y2)
 dx = x2-x1
 dy = y2-y1
 sx = deltasign(dx)
 sy = deltasign(dy)
 local x = x1
 local y = y1
 local adx = math.abs(dx)
 local ady = math.abs(dy)
 local er,e2

if adx > ady then er =  adx 
else er = - ady
end 

er = math.floor(er / 2)

while 1 do
  plotpixel(0,x,y)
  plotcolor(8192,x,y,colorfg)
  if x == x2 and y == y2 then return end
  e2 = er
  if e2 > -adx then er = er - ady; x = x + sx  end
  if e2 <  ady then er = er + adx; y = y + sy  end
  if x<0 or x > 255 or y < 0 or y > 191 then return end
end  -- while
end -- function


function clearscreentms()
tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]
mem = tms.spaces["vram"]
local addr
for addr = 0,6143 do mem:write_u8(addr,0) end
end

function circlerandomcolor(step,size)
local i
for i=0,360,step do linedraw(128,96,128+math.cos(i/360*2*math.pi)*size,96+math.sin(i/360*2*math.pi)*size,math.floor(math.random()*15)) end
end

function initpatterntms()
local pat
for pat = 0,768-1 do
   mem:write_u8(pat+0x3800,pat % 256)
end
end


clearscreentms()
initpatterntms()
for i = 0,255,16 do linedraw(i,0,0,192,math.floor(i/16)) end
circlerandomcolor(1,50)
for i = 0,255,16 do linedraw(i,0,255,191,math.floor(i/16)) end

Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
I wanted to see if I could rip atari 2600 graphics from the game Stampede, so I wrote a little lua script to dump the ram from the 2600.

I didn't know how much to grab, so I went for 4k. I now know that Stampede is a 2k cartridge.

Code
mem=manager:machine().devices[":maincpu"].spaces["program"]

-- read ram and save to a file

outfile = assert(io.open("2600_dump_file", "wb"))

for i=0x1000,0x2000-1 do
  outfile:write(string.char(mem:read_u8(i)))
end

assert(outfile:close())

and once you have the 2600_dump_file saved, you can run this script on the apple2e driver with -sl4 arcbd which will make the following display:

The horse animates and you can move it left right/up and down.


I always wondered why the legs of the horse had an interlaced effect. That's because of the HMOVEs so the legs can split and display wider than the 8 pixels in a byte.

[Linked Image from i.imgur.com]

Code
-- ==============================================================
-- read datablock from a file and close it

infile = assert(io.open("2600_dump_file", "rb"))

datablock = infile:read("*all")    

assert(infile:close())

-- ====================================================================

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc3) -- dbl size
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]):write(0,0)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_colour"]):write(0,0x2000)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_nametbl"]):write(0,0x3800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_mode"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spritepattern"]):write(0,0x1800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spriteattribute"]):write(0,0x1f80)
--set background to 4
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[7]"]):write(0,0xf4)

mem=manager:machine().devices[":sl4:arcbd:arcbd_tms"].spaces["vram"]

function plotpixel(screenaddr,x,y)
local byteaddr = screenaddr + math.floor(y/8) * 256 + math.floor(y % 8) + math.floor(x/8) * 8
if x>=0 and x <=255 and y>=0 and y <=191 then
mem:write_u8(byteaddr,mem:read_u8(byteaddr)| (1 << (7-(x%8))))
end
end


function plotcolor(screenaddr,x,y,colorfg)
local byteaddr = screenaddr + math.floor(y/8) * 256 + math.floor(y % 8) + math.floor(x/8) * 8
if x>=0 and x<=255 and y>=0 and y<=191 then
--foreground single color
mem:write_u8(byteaddr,(mem:read_u8(byteaddr)& 0x0) | (math.floor(colorfg) << (4)) )
end
end

function deltasign(x)
if x<0 then return -1
elseif x==0 then return 0
elseif x>0 then return 1
else return 0
end
end

function linedraw(x1,y1,x2,y2,colorfg)
-- using basic code converted to lua from:
-- https://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm

 x1 = math.floor(x1);x2 = math.floor(x2);y1 = math.floor(y1);y2 = math.floor(y2)
 dx = x2-x1; dy = y2-y1
 sx = deltasign(dx); sy = deltasign(dy)
 local x = x1; local y = y1
 local adx = math.abs(dx)
 local ady = math.abs(dy)
 local er,e2

if adx > ady then er =  adx 
else er = - ady
end 

er = math.floor((er / 2)+0.5)  -- INT rounding because math.floor rounding doesn't work for 1 pixel lines

while 1 do
  plotpixel(0,x,y)
  plotcolor(8192,x,y,colorfg)
  if x == x2 and y == y2 then return end
  e2 = er
  if e2 > -adx then er = er - ady; x = x + sx  end
  if e2 <  ady then er = er + adx; y = y + sy  end
  if x<0 or x > 255 or y < 0 or y > 191 then print("hit edge",x1,y1,x2,y2) return end
end  -- while
end -- function

function drawbox(x1,y1,x2,y2,col)
 linedraw(x1,y1,x2,y1,col)
 linedraw(x2,y1,x2,y2,col)
 linedraw(x2,y2,x1,y2,col)
 linedraw(x1,y2,x1,y1,col)
end


function clearscreentms()
tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]
mem = tms.spaces["vram"]
local addr
for addr = 0,6143 do mem:write_u8(addr,0) end
end

function initpatterntms()
local pat
for pat = 0,768-1 do
   mem:write_u8(pat+0x3800,pat % 256)
end
end

function initcolortms(fg,bg)
for addr = 0,6143 do mem:write_u8(addr+8192,bg|(fg<<4)) end end


function clstms()
clearscreentms()
initpatterntms()
initcolortms(15,4)
end

clstms()

function reversebits(x)
local outbyte = 0
for bit=0,7 do
  if(x & (1<<bit))~=0 then outbyte = outbyte | (1<<(7-bit)) end
end
return outbyte
end

function draw2600intoscreendirect()
for i=0,4096-1 do
  mem:write_u8(i,reversebits(string.byte(datablock,(i+1))))  -- datablock index starts at 1
end
end

clstms()

function draw2600intoscreen()
xpos = 0; ypos = 0
for i = 4096-1,4096-2048-1,-1 do
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(i+1))) & (1<<bit))~=0 then linedraw(xpos+bit,ypos,xpos+bit,ypos,7) end
  end
  ypos = ypos + 1
  if ypos >= 128+16 then ypos = 0; xpos = xpos + 16; end
end
end

clstms()
draw2600intoscreen()

function stampededogie(p8d,p8f)
--linedraw(xpos,ypos,xpos,ypos,1)
for offset = 0xf,1,-1 do
grp1 =p8f+offset
hmove=p8d+offset-1
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(grp1+1))) & (1<<bit))~=0 then linedraw(xpos+bit,ypos,xpos+bit,ypos,7) end
  end
  hmoveval = (string.byte(datablock,(hmove+1))>>4)
  if hmoveval >= 8 then hmoveval = hmoveval - 16 end
  xpos = xpos - hmoveval
  ypos = ypos + 1
  if ypos >= 128+64 then ypos = 128+32; xpos = xpos + 16; end
end
end

xpos = 32;       ypos = 128+48; stampededogie(0x6c9,0x67d);
xpos = 32+1*16;  ypos = 128+48; stampededogie(0x6c9,0x66e);
xpos = 32+2*16+6;ypos = 128+48; stampededogie(0x6ac,0x68b)

function stampede_horse(p8b,p8d,p8f) 
--p8b is ptr to hmp0, p8d is ptr to nusiz0, p8f is ptr to grp0
xpos = xpos + 32
ypos = 128+24
for offset=0x19,1,-1 do
grp0 =p8f+offset
hmove=p8b+offset-1  -- hmove happens to "next line"
nusiz=p8d+offset
-- follows the atari 2600 stampede code which ORs these 2 together
nusiz=string.byte(datablock,(nusiz+1)) | (string.byte(datablock,(hmove+1+1))&5)
nusiz=nusiz & 0xd
  if (nusiz & 7) == 5 then dbl=2 else dbl=1 end
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(grp0+1))) & (1<<bit))~=0 then 
          linedraw(xpos+bit*dbl,ypos,xpos+(bit+1)*dbl-1,ypos,7+dbl)
    end
  end
  hmovedelta = (string.byte(datablock,(hmove+1))>>4)
  if hmovedelta >= 8 then hmovedelta = hmovedelta - 16 end
  xpos = xpos - hmovedelta
  ypos = ypos + 1
  if ypos >= 128+64 then ypos = 128+24; xpos = xpos + 32; end
end
end

xpos=64;      stampede_horse(0x74d,0x6c7,0x71a); 
xpos=64+1*32; stampede_horse(0x766,0x6c7,0x700); 
xpos=64+2*32; stampede_horse(0x74d,0x6c7,0x700); 
xpos=64+3*32; stampede_horse(0x77f,0x6c3,0x734);

function drawblock(addr,offset1,offset2)
ypos0 = ypos
for i=addr+offset1,addr+offset2,-1 do
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(i+1))) & (1<<bit))~=0 then 
       linedraw(xpos+bit,ypos,xpos+bit,ypos,10)
    end
  end    
  ypos = ypos + 1
end
xpos = xpos + 8
ypos = ypos0
end

function stampede_activision()
drawblock(0x668,6,0) -- act
drawblock(0x660,6,0) -- iv
drawblock(0x658,6,0) -- isi
drawblock(0x650,6,0) -- on
end

xpos = 128; ypos= 128+56
stampede_activision()

function stampede_skull()
drawblock(0x69b,9,1)
end

xpos = 64;ypos = 128+20
stampede_skull()

function stampede_0123456789()
for num = 0,9 do
drawblock(0x600+num*8,6,0)
end
end

xpos = 0;  ypos = 128+30; stampede_0123456789()

function xytoaddress(x,y)
--print(x,y,math.floor(y/8)*256+(y%8)+math.floor(x/8)*8)
x = math.floor(x)
y = math.floor(y)
return math.floor(y/8)*256+(y%8)+math.floor(x/8)*8
end

for box=0,3 do drawbox(80+32*box,150,80+32*(box+1)-1,150+31,9) end

-- 4 different 16x16 blocks

bytepos=0x1800; 
for box = 0,3 do
for cellx = 0,1 do for celly = 0,1 do for j = 0,1 do for i=0,15 do mem:write_u8(bytepos,mem:read_u8(xytoaddress(80+8*j+16*cellx+box*32,150+i+16*celly))); bytepos = bytepos + 1; end end end end end


spriteatt = 0x1f80

horsex = 25
horsey = 25

scale = 2

function setsprite(sprnum,sprimgnum)
for celly = 0,1 do
for cellx = 0,1 do
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 0, horsey+16*celly*scale)
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 1, horsex+16*cellx*scale)
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 2,(cellx * 2 + celly)*4+16*sprimgnum)
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 3, 11)
end
end
end


setsprite(0,0)


dispatch_list={}


function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end


function dispatch_list_remove(a_func)
for my_index,my_func in pairs(dispatch_list) do if my_func == a_func then table.remove(dispatch_list,my_index) end end
end

function print_dispatch_list() for my_index,my_func in pairs(dispatch_list) do print(my_func) end end



if already_registered_frame_dispatcher == nil then
   emu.register_frame(frame_dispatcher);
   already_registered_frame_dispatcher = 1
end

function cld()
dispatch_list = {}
end


delaycounter1 = 0
spriteimageseq = {0,1,2,1}
spriteimageseqnum = 1


function every_frame()
--  everydelay(1,delaycounter1)
  
  delaycounter1 = (delaycounter1+1)%5
  if delaycounter1 == 0 then 
           spriteimageseqnum = (((spriteimageseqnum + 1)-1) % #spriteimageseq)+1
  end

  inp = manager:machine():input()
  if inp:code_pressed(inp:code_from_token("KEYCODE_UP")) then 
     horsey = horsey - 2
   end

  if inp:code_pressed(inp:code_from_token("KEYCODE_DOWN")) then 
     horsey = horsey + 2
  end
      
  if inp:code_pressed(inp:code_from_token("KEYCODE_RIGHT")) then 
    horsex = horsex + 2
  end
  if inp:code_pressed(inp:code_from_token("KEYCODE_LEFT")) then 
    horsex = horsex - 2
  end


  setsprite(0,spriteimageseq[spriteimageseqnum])
  

end

table.insert(dispatch_list,every_frame)

Joined: Mar 2001
Posts: 17,217
Likes: 234
R
Very Senior Member
Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,217
Likes: 234
Coming soon....

[Linked Image from rbelmont.mameworld.info]

It actually works except for detecting slot 6 and dropping the speed right now, so obviously the Disk II is unhappy with that smile

Joined: Feb 2014
Posts: 1,102
Likes: 173
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,102
Likes: 173
I finally figured out how to read the apple joystick from lua.

Code
-- this is a little function to print a table

function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end


 printt(manager:machine():ioport().ports)

:X5	sol.ioport_port*: 0x55d3d11cd778
:joystick_1_y	sol.ioport_port*: 0x55d3d11cd7f8
:X3	sol.ioport_port*: 0x55d3d11d2fa8
:keyb_special	sol.ioport_port*: 0x55d3d11cd958
:joystick_buttons	sol.ioport_port*: 0x55d3d11cd9c8
:joystick_2_y	sol.ioport_port*: 0x55d3d11cda38
:X7	sol.ioport_port*: 0x55d3d11cd698
:joystick_2_x	sol.ioport_port*: 0x55d3d11cdaa8
:a2_config	sol.ioport_port*: 0x55d3d11cd5b8
:X4	sol.ioport_port*: 0x55d3d11cd7b8
:joystick_1_x	sol.ioport_port*: 0x55d3d11cd548
:X2	sol.ioport_port*: 0x55d3d52ee878
:X1	sol.ioport_port*: 0x55d3d52ee8f8
:X8	sol.ioport_port*: 0x55d3d11cd628
:X0	sol.ioport_port*: 0x55d3d11d2cd8
:X6	sol.ioport_port*: 0x55d3d11cd708

and if you look at the apple2e.cpp code, you can see that it maps right up to this:

Code
	PORT_START("joystick_buttons")
	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)  PORT_PLAYER(1)            PORT_CODE(KEYCODE_0_PAD)    PORT_CODE(JOYCODE_BUTTON1)
	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2)  PORT_PLAYER(1)            PORT_CODE(KEYCODE_ENTER_PAD)PORT_CODE(JOYCODE_BUTTON2)
	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1)  PORT_PLAYER(2)            PORT_CODE(JOYCODE_BUTTON1)

so to read the buttons you can do:

Code
print(manager:machine():ioport().ports[":joystick_buttons"]:read())
0
and to test it in an if statement:

Code
if (manager:machine():ioport().ports[":joystick_buttons"]:read() & 0x10) ~= 0 then
  -- button 1 pressed
end
if (manager:machine():ioport().ports[":joystick_buttons"]:read() & 0x20) ~= 0 then
  -- button 2 pressed
end


The joystick axes come in under the names "joystick_1_x" and "joystick_1_y"

Looking at apple2e.cpp we have:
Code
static INPUT_PORTS_START( apple2_joystick )
	PORT_START("joystick_1_x")      /* Joystick 1 X Axis */
	PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("P1 Joystick X")
	PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
	PORT_KEYDELTA(JOYSTICK_DELTA)
	PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
	PORT_MINMAX(0,0xff) PORT_PLAYER(1)
	PORT_CODE_DEC(KEYCODE_4_PAD)    PORT_CODE_INC(KEYCODE_6_PAD)
	PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH)    PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)

	PORT_START("joystick_1_y")      /* Joystick 1 Y Axis */
	PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("P1 Joystick Y")
	PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
	PORT_KEYDELTA(JOYSTICK_DELTA)
	PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
	PORT_MINMAX(0,0xff) PORT_PLAYER(1)
	PORT_CODE_DEC(KEYCODE_8_PAD)    PORT_CODE_INC(KEYCODE_2_PAD)
	PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH)      PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)

and in lua we can read it with:

Code
print(manager:machine():ioport().ports[":joystick_1_x"]:read())
128
print(manager:machine():ioport().ports[":joystick_1_y"]:read())
128

Note that to get the input events for the joystick movement and buttons, the apple2e window must be selected.

So if you do a print(manager:machine():ioport().ports[":joystick_buttons"]:read()) from the lua console you will get zero unless you select the apple2e window, hold the joystick button(s), click on the lua console window and then do your print statement.

What's kind of interesting is that with the focus taken away from the window, the joystick and buttons will center or release but won't move away from center.

Page 11 of 80 1 2 9 10 11 12 13 79 80

Link Copied to Clipboard
Who's Online Now
2 members (shattered, Reznor007), 268 guests, and 4 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,320
Posts121,944
Members5,074
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Forum hosted by www.retrogamesformac.com