FYI - The latest WOZ disks for Adventureland and Pirate Adventure do not appear to work in MAME once you get to the actual game. Could this be more weak bit issues from the copy protection?
No, the protection is a crafted track with timing bits, but not weak bits. You'll have to be more specific about what's not working. I just booted Adventureland in 0.209 and I can walk around and do stuff. It's awfully slow to load. Perhaps you were not patient enough?
and then I check the button status and if nonzero, find out which button and use that to set the values returned to the x and y axis so the software thinks the pen is over the button.
Code
if (m_tablet_menu_buttons->read())
{
int buttonstate=m_tablet_menu_buttons->read();
for(int i=0;i<22;i++)
if (buttonstate & (1<<i))
m_timervalue = (m_tabletmax-m_tabletmin)/255.0*(i*250.0/22+(250.0/22/2))+m_tabletmin; // multiply by 250/22 and then offset by half of 250/22 so it's in the middle.
}
and I can draw like it's 1980! (The graphics tablet software isn't quite DeluxePaint. 8-)
I am trying to get some lua scripting going for a layout, and I can't get it to do anything.
Sticking a print("hello") statement doesn't even seem to work.
=====================
Ok, I think I've found the problem, for some reason I don't have the layout plugin activated.
With -plugin layout on the command line, I get some layout action. Yes!
But I can't print anything? And manager isn't available...
Let's look at init.lua in plugins/layout:
It redefines machine to be manager:machine()
so normal lua code that uses manager:machine() to access machine, just becomes machine.
Code
function layout.startplugin()
local scripts = {}
local function prepare_layout(script)
local env = { machine = manager:machine(), pairs = pairs, ipairs = ipairs, emu = emu, print = print,
table = { insert = table.insert, remove = table.remove } }
I added a few things, like emu and print, so now I can do this, a drive led that shows activity:
Code
<script>
local layout = {}
local function bool10(a) if a then return 1 else return 0 end end
function layout.frame()
--print("oh yeah") -- it will print oh yeah for every frame if you uncomment it
machine:outputs():set_value("drive1led",
bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)==1) &
bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/external_io_select"]):read(0) == 0))
machine:outputs():set_value("drive2led",bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)==1) &
bool10 (emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/external_io_select"]):read(0) == 1))
end
return layout,"apple2"
</script>
So in the upper right, I've got two drive LEDs that light up when the respective disk drive is active. Now all I need to do is activate those drive sounds again. 8-)
I was doing a catalog at the time the snapshot was taken so the drive 1 light was on.
I noticed that it flickers more than the apple disk drives would normally, using this:
Code
bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)>0)
instead of
bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)==1)
local layout = {}
local function iif(a,b,c) if a then return b else return c end end
function layout.frame()
machine:outputs():set_value("floppytrack1",
iif(
(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)>0),
emu.item(machine.devices[":sl6:diskiing:0:525"].items["0/cyl"]):read(0),999)
)
machine:outputs():set_value("floppytrack1sub",
iif(
(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)>0),
emu.item(machine.devices[":sl6:diskiing:0:525"].items["0/subcyl"]):read(0),999)
)
writing 999 to a two digit counter makes it disappear, so the track display disappears when it's inactive.
I figured that red would look good:
A floppy with sounds, leds and a track display. Awesome!
I came across a disk image for the computer eyes video digitizer (the very first one that hooked up to the gameport). I thought I'd load it up just to see if it'd do anything. Running a capture I saw that if you pressed the controller button, it would change the screen display. Cool!
Tapping the controller button as it captures: (kinda looks like a barcode)
So this is a 1 bit capture device, capturing 280x192 and it captures 1 bit for each scanline, scanning left to right across the screen.
Well, why not try to send the capture program some data? Gimp is pretty useful in that it can save data in a raw format. I'll create a little 280x192 rgba bitmap and export it as raw data. (gimp seems to want to add an alpha channel to the image)
We'll add some stuff to apple2.cpp:
Make a buffer to hold a picture:
Code
uint m_computereyescapturebuffer[192][280]; // [280][192] that is column major, we want [192][280]
int m_cex, m_cey;
Give it a save_item so we can access it from lua:
Code
save_item(NAME(m_computereyescapturebuffer));
Reset the position when we reset AN0.
Code
WRITE_LINE_MEMBER(apple2_state::an0_w)
{
m_cex=0;
m_cey=0;
printf("set cex,cey to zero AN0 %x\n",state);
m_an0 = state;
}
Read a pixel from button 1 and increment the position:
Code
READ8_MEMBER(apple2_state::flags_r)
{
int old_m_cey=m_cey;
int old_m_cex=m_cex;
if ((m_cex==0) && (m_cey==0)) printf(" AN STATUS: %x %x %x %x\n",m_an0,m_an1,m_an2,m_an3);
u8 uFloatingBus7 = read_floatingbus() & 0x7f;
// Y output of 74LS251 at H14 read as D7
switch (offset)
{
case 0: // cassette in (accidentally read at $C068 by ProDOS to attempt IIgs STATE register)
return (m_cassette->input() > 0.0 ? 0x80 : 0) | uFloatingBus7;
case 1: // button 0
return ((m_joybuttons->read() & 0x10) ? 0x80 : 0) | uFloatingBus7;
case 2: // button 1
m_cey=m_cey+1;
if(m_cey>191) {m_cey=0; m_cex=m_cex+1;}
return (m_computereyescapturebuffer[std::min(old_m_cey,191)][std::min(old_m_cex,279)]>(128*m_an2+64*m_an1+32*m_an3))? 0x80:0;
// capture threshold seems to be 128 *m_an2 + 64 * m_an1 + 32 * m_an3
and since the main machine's saveitems aren't accessible otherwise, we'll add a function to luaengine.cpp
quick = emu.items()["Apple ][+/:/0/m_computereyescapturebuffer"] print(quick)
for i=0,280*192-1 do emu.item(quick):write(i,a:byte(1+i*4)) end -- just grab the red component to make it simple
It's a bit of a hack (yeah ok, it's a total hack), in that I'm not really getting the timing and sync right, I'm just incrementing the read position based on how many times it reads button 1, and resetting that position when it resets AN0.
I want to figure out how to capture a frame with v4l2 and load that up.
Mame logo:
original bitmaps:
8 level capture versus a 2 level capture:
The 8 bit guy has a video using a computer eyes on a c64 at At the 6:55 mark you can see what's actually inside, it's pretty simple.
Digital Vision put up a webpage for the history of their products:
There's a Video Digitiser for the BBC Micro I'd like to emulate at some point, but we don't yet support any kind of video input. Would implementing a bitmap_image_device be a suitable compromise to allow emulating such devices?
With a bitmap_image_device you'd be able to provide a bmp image for the emulated device to capture. Waste of time or worthwhile?
BBC Model B, ATPL Sidewise, Acorn Speech, 2xWatford Floppy Drives, AMX Mouse, Viglen case, etc.
The Digital Vision website indicates that the Apple II, C64, and Atari 800 versions are the same hardware with different connection methods (game port on A2 and Atari, user port on the Commodore) so we could potentially pull one of those "only in MAME" things if the software for all 3 can be found.
I found a c64 computereyes disk on the net (just search for "computereyes c64") and thought I'd have a look.
It uses the userport and from the info at: https://www.c64-wiki.com/wiki/CIA the important addresses are $DD01 (read/write data) and $DD03 (sets io direction).
Making some hacky changes to c64.cpp:
Code
uint m_computereyescapturebuffer[200][320]; // resolution of c64 capture is 320x200
int m_cex, m_cey;
int m_portb_write;
add the save item:
Code
save_item(NAME(m_computereyescapturebuffer));
make some changes to the cia2:
Code
READ8_MEMBER( c64_state::cia2_pb_r )
{
int threshold = ((m_portb_write & (1<<2)) ? 128 : 0) + // bit 2 = threshold bit 7
((m_portb_write & (1<<1)) ? 64 : 0) + // bit 1 = threshold bit 6
((m_portb_write & (1<<0)) ? 32 : 0) ; // bit 0 = threshold bit 5
//threshold = threshold; // compiler keeps complaining about unused variables!!!
int valtoreturn = m_computereyescapturebuffer[std::min(m_cey,199)][std::min(m_cex,319)]>threshold ? 0x40:0; // return capture in bit 6, sync is bit 7
//int valtoreturn = m_joy2->read_joy()&(1<<5) ? 0x40:0; // return capture in bit 6, sync is bit 7, joystick button to set the capture bit
// find address of pc
std::string mycontext = machine().describe_context();
int myaddr = stoi(mycontext.substr(mycontext.find("(")+1,4),nullptr,16);
if (myaddr==0xc101) // only increment our position if we are reading $DD01 at address 0xc101 since we read $DD01 in multiple places
{
m_cey=m_cey+1;
if(m_cey>199) {m_cey=0; m_cex=m_cex+1;}
}
return valtoreturn;
return m_user_pb;
}
WRITE8_MEMBER( c64_state::cia2_pb_w )
{
m_user->write_c((data>>0)&1);
m_user->write_d((data>>1)&1);
m_user->write_e((data>>2)&1);
m_user->write_f((data>>3)&1);
m_user->write_h((data>>4)&1);
m_user->write_j((data>>5)&1);
m_user->write_k((data>>6)&1);
m_user->write_l((data>>7)&1);
printf("wrote %x to pb_w m_user_pb=%x\n",data,m_user_pb); // why doesn't m_user_pb == data?
if ((data&0xf) != (m_portb_write&0xf)) {printf("LOW NIBBLE CHANGED RESETTING m_cex,m_cey=0\n");m_cex=0;m_cey=0;}
m_portb_write=data;
}
and our pic must be 320x200 now, so I made a little file in Gimp to "capture"
Code
f=assert(io.open("c64raw.data"))
a=f:read("*a") f:close() print(#a)
quick = emu.items()["Commodore 64 (NTSC)/:/0/m_computereyescapturebuffer"] print(quick)
for i=0,320*200-1 do emu.item(quick):write(i,a:byte(1+i*4)) end -- just grab the red component to make it simple
The first thing I'd thought I'd try was to hook up the joystick 2 button and get it to return some values into bit 6 of the user port b at $dd01.
After that worked I tried to get a picture to load, but I noticed that it keeps reading from $dd01 in multiple locations since it gets the sync bit in bit 7, so we only increment the position when we read at address $c101.
Using the joystick 2 button:
It gets a higher resolution 320x200 than the apple's 280x192 capture which is a slight improvement, but still black and white. Unfortunately, it blanks the screen while capturing (probably to avoid any cpu slowdown) so you can't see what's going on.