Previous Thread
Next Thread
Print Thread
#124445 04/21/25 05:36 PM
Joined: Feb 2014
Posts: 1,184
Likes: 218
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,184
Likes: 218
So I was experimenting with the BIT90 (colecovision clone) computer and wanted to paste in the bit90 demo program, however it was too big for the buffer in the natural keyboard.

In natkeyboard.cpp I changed:


const int KEY_BUFFER_SIZE = 32768; // was 4096, not quite enough for the whole thing, 32k is plenty large


and also had to change the delay on CR so that it wouldn't clobber the beginning of the next line


// otherwise, default to constant delay with a longer delay on CR
// return attotime::from_msec((ch == '\r') ? 200 : 50);
return attotime::from_msec((ch == '\r') ? 1500 : 75);



then I could do a post from lua

manager.machine.natkeyboard:post([[
0001 GOTO 7000
0002 CLEAR :POKE 28693,1930
0003 CALL 9515
0004 CALL SCREEN(1,2)
0007 E$="C3D3E3F3G3F3E3D3":F$="E3F3G3A3B3A3G3F3"
0008 G$="E3F3G3A3B3A3G3F3":H$="G3A3B3+C3+D3+C3B3A3"
0012 A$="C3D3E3D3":B$="E3F3G3F3":C$="G3A3B3A3"
0013 A0$=E$&E$&F$&F$&"G3A3B3+C3+D3+E7R3+ER3+ER3+D9+C9"
0014 A1$=G$&G$&H$&H$&"B3+C3+D3+E3+F3+G7R3+GR3+GR3+A9+G9"

]]))

Joined: Feb 2014
Posts: 1,184
Likes: 218
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,184
Likes: 218
and how about a way to stop a post in progress:


add a variable m_stopflag in natkeyboard.h

Code
    u8 m_stopflag = 0;

    void stop(){ m_stopflag=1;}


and in natkeyboard.cpp

Code
void natural_keyboard::timer(s32 param)
{
...	
	if (advance)
		{
			m_fieldnum = 0;
			m_status_keydown = !m_status_keydown;

			// proceed to next character when keydown expires
			if (!m_status_keydown)
			{
				m_bufbegin = (m_bufbegin + 1) % m_buffer.size();
				if (m_stopflag) {m_stopflag=0; m_bufbegin = m_bufend;}  // check the stopflag
			}
		}
	}

	// need to make sure timerproc is called again if buffer not empty
	if (!empty())
		m_timer->adjust(choose_delay(m_buffer[m_bufbegin]));
}

and then in luaengine:

emu["keypost"] = [this] (const char *keys) { machine().natkeyboard().post_utf8(keys); };
emu["keystop"] = [this] () { machine().natkeyboard().stop(); };



so now I can stop a post with emu.keystop()

Last edited by Golden Child; 04/21/25 06:21 PM.
Joined: Mar 2002
Posts: 1,375
Likes: 133
H
hap Offline
Very Senior Member
Very Senior Member
H Offline
Joined: Mar 2002
Posts: 1,375
Likes: 133
The buffer is a vector that's resized, 4KB chunk size should be ok.
But I think there's a bug here?

orig:
Code
	// add to the buffer, resizing if necessary
	m_buffer[m_bufend++] = ch;
	if ((m_bufend + 1) % m_buffer.size() == m_bufbegin)
		m_buffer.resize(m_buffer.size() + KEY_BUFFER_SIZE);
	m_bufend %= m_buffer.size();

should be:
Code
	// add to the buffer, resizing if necessary
	m_buffer[m_bufend] = ch;
	m_bufend = (m_bufend + 1) % m_buffer.size();
	if (m_bufend == m_bufbegin)
	{
		m_buffer.insert(m_bufbegin, KEY_BUFFER_SIZE);
		**edit** nope, that's a wrong way of using insert(), but you get what I mean here...
		**edit2**: ah, I think the syntax is insert(pos, size, val)
		m_bufbegin += KEY_BUFFER_SIZE;
	}

After that, the full() check in post() should never hit and can be removed.

Last edited by hap; 04/21/25 06:59 PM.
1 member likes this: Golden Child
Joined: Mar 2002
Posts: 1,375
Likes: 133
H
hap Offline
Very Senior Member
Very Senior Member
H Offline
Joined: Mar 2002
Posts: 1,375
Likes: 133
vector resize bug is fixed, I also added an arbitrary limit so users with either broken LUA scripts (or bullying MAME by pasting 1GB text files multiple times in a row) won't lock up MAME with all the memory reallocations.
The limit is more than enough, about 2 bibles worth of characters.

Those delays you ran into are not just for pasting, but for natural keyboard too. I already find 200ms for the Enter key laggy. But yes, it's known that the current settings can be too fast for pasting on 8-bit homecomputers or old LED display terminals.

Joined: Feb 2014
Posts: 1,184
Likes: 218
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,184
Likes: 218
Code

	// add to the buffer, resizing if necessary
	m_buffer[m_bufend] = ch;
	if ((m_bufend + 1) % m_buffer.size() == m_bufbegin)
	{
		if (m_buffer.size() >= KEY_BUFFER_MAX_SIZE)
			return;

		m_buffer.insert(m_buffer.begin() + m_bufbegin, KEY_BUFFER_CHUNK_SIZE, INVALID_CHAR);
		m_bufbegin += KEY_BUFFER_CHUNK_SIZE;
	}

	m_bufend = (m_bufend + 1) % m_buffer.size();



I pasted your new code in and found a bug,

say we have a buffer sized 4k BUFFER_CHUNK_SIZE = 0x1000;

and our initial post size is larger than this

so bufend keeps getting incremented to 4095 and bufstart is zero


than at this point, when you execute the code, it checks

if ((m_bufend + 1) % m_buffer.size() == m_bufbegin) and says yes, we need to make the buffer bigger,

so it increases the buffersize by 4096 and also increments the bufbegin to now be 4096

0..4095 all new invalid 4096 = newbufbegin, but bufend is still 4095,


m_bufend = (m_bufend + 1) % m_buffer.size(); <--- buffer size is now 8192

so we set bufend to 4096 but bufstart is now 4096, when bufend should now be zero

Now any more characters will start stomping over the freshly moved characters.


so we need to check if bufend > bufstart and if so, also increment bufend when we increment bufstart (since we are inserting characters before where the bufend is "pointing")


Code
// add to the buffer, resizing if necessary
	m_buffer[m_bufend] = ch;
	if ((m_bufend + 1) % m_buffer.size() == m_bufbegin)
	{
		if (m_buffer.size() >= KEY_BUFFER_MAX_SIZE)
			return;

		m_buffer.insert(m_buffer.begin() + m_bufbegin, KEY_BUFFER_CHUNK_SIZE, INVALID_CHAR);

if (m_bufend > m_bufbegin) m_bufend += KEY_BUFFER_CHUNK_SIZE;  // this fixes the bufend 
		m_bufbegin += KEY_BUFFER_CHUNK_SIZE;
	}

	m_bufend = (m_bufend + 1) % m_buffer.size();


I also stuck a popmessage in natural_keyboard::timer to show how much keybuffer is remaining to give some feedback.

Code
	machine().popmessage(std::string("KeyBuffer: ") + 
		std::to_string((m_bufend < m_bufbegin ? m_buffer.size() : 0) + m_bufend - m_bufbegin) +
		std::string(" / ") + 
		std::to_string(m_buffer.size()));

Last edited by Golden Child; 04/22/25 06:56 AM.
Joined: May 2009
Posts: 2,225
Likes: 387
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,225
Likes: 387
Originally Posted by Golden Child
so we set bufend to 4096 but bufstart is now 4096, when bufend should now be zero

Now any more characters will start stomping over the freshly moved characters.

Please explain your logic. Why should bufend be zero? When the 4097th character of a paste larger than 4096 characters comes in, it will arrive at m_buffer[4096], just as it ought to. What are these "freshly moved characters," where is the data in m_buffer being "moved"?

Joined: Mar 2002
Posts: 1,375
Likes: 133
H
hap Offline
Very Senior Member
Very Senior Member
H Offline
Joined: Mar 2002
Posts: 1,375
Likes: 133
Yeah it's a bug, for some reason it didn't trigger when I tested it with -natural.

eg. set KEY_BUFFER_CHUNK_SIZE to 5
I paste: helloworld

mame.exe driver -natural
helloworld

mame.exe driver -nonatural
world

Joined: May 2009
Posts: 2,225
Likes: 387
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,225
Likes: 387
Oh, I think I see it. It's a circular buffer, so, yeah. Thanks for clarifying.


Link Copied to Clipboard
Who's Online Now
0 members (), 117 guests, and 2 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,363
Posts122,479
Members5,082
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
Powered by UBB.threads™ PHP Forum Software 8.0.0