IKBD Keyboard Joystick trouble

All 680x0 related coding posts in this section please.

Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

IKBD Keyboard Joystick trouble

Postby Zamuel_a » Fri Jul 12, 2013 9:14 pm

I want to use both the Joystick and keyboard and I setup the "normal" (I think) way of doing it with the IKBD and it works fine for the joystick. For the keyboard I'm just polling $ffffc02 and that also works but it I press the keys rapidly I miss data so I planned to put the keyboard reader under $118 aswell and that seems to work, but now the joysticks doesn't work! I can keep everything in my code except the read of $ffffc02 before they stops working so it seems like reading this register prevents the joystick to be handled. I'm not sure how to do it. I need a fast way (for game) to read both keyboard and joystick and be as interrupt friendly as possible.

Code: Select all

IKBD.turnOnJoystick

   movem.l   d0/a0,-(sp)

   move.w   #34,-(sp)
   trap   #14
   addq.l   #2,sp         ;return IKBD vector table

   move.l   d0,ikbd_vec      ;store IKBD vectors address
   move.l   d0,a0         ;a0 points to IKBD vectors
   move.l   24(a0),old_joy      ;backup old joystick vector      
   move.l   #readjoy,24(a0)      ;input my joystick vector

   move.l   #joy_on,-(sp)      ;pointer to IKBD instructions
   move.w   #0,-(sp)      ;instruction length - 1
   move.w   #25,-(sp)      ;send instruction to IKBD
   trap   #14
   addq.l   #8,sp

   movem.l   (sp)+,d0/a0
   rts


Code: Select all

readjoy   move.b   1(a0),joy         store joy 0 data
   move.b   2(a0),joy+1         store joy 1 data
   rts


Here is the actual code that doesn't work. The part between the MOVEM statements are new and is what I used a simple polling routing before. It works by placing it here for the keyboard, but the joysticks doesn't work anymore...

Code: Select all

;Lower IKBD interrupt below the priority of the HBL
IKBD.setIKBDirqLow
   move.l   $118,oldikbd
   move.l   #newikbd,$118
   rts

newikbd   movem.l   d0-d1/a1,-(sp)
   lea   keyboard_buffer,a1

   move.b   $fffffc02.w,d0
   move.b   d0,d1
   and.l   #$7F,d1
   adda.l   d1,a1   

   btst   #7,d0         ;check if it's a press or release
   bne.s   brkcode   
   move.b   #1,(a1)      
   bra   next
      
brkcode   move.b   #0,(a1)      
next   movem.l   (sp)+,d0-d1/a1

   move.w   d0,-(sp)
   move.w   sr,d0
   and.w   #$f8ff,d0
   or.w   #$500,d0
   move.w   d0,sr
   move.w   (sp)+,d0
   dc.w   $4ef9
oldikbd   dc.l   0
   illegal
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Sun Jul 14, 2013 3:24 pm

Noone knows how to make a keyboard routine that actually works? Every game has it so there must be a way :wink: But I can never find any good solution when I search for it. I tried again with reading $fffc00 as discussed here:
http://www.atari-forum.com/viewtopic.php?f=68&t=24646#p226500

but it doesn't work. It doesn't give anything when I tries to read that register, atleast not under Steem or Hatari (haven't tried it on a real machine, but I need a version that works under emulators anyway)

I had planned to release the current progress on my Metroid game, but since the keyboard controller is crappy it's no fun to play.
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Sun Jul 14, 2013 4:39 pm

I'm reasonably confused by what you're trying to do here.

I don't understand the 'lower keyboard priority below HBL' - that isn't possible in the ST. And I don't see the state machine in your interrupt routine that is required to parse the IKBD command stream, so I don't see how you'll treat joystick messages as actually joystick messages...

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Sun Jul 14, 2013 5:16 pm

I have copied the code from somethere and it works for joysticks without any problems. The lower IKBD priority is also a code I found on the net and it makes Timer B more stable so it's not HBL = $68, but Timer B.
http://www.atari-forum.com/wiki/index.php?title=Lowering_the_priority_of_the_IKBD_interrupt

I didn't include EVERYTHING in the example here. The "joy" variable has all the joystick data and can be read at any time. What I want to do is to read both keyboard and joystick but I have never found any information on how to do that, only a few code pieces here and there.
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Mon Jul 15, 2013 7:02 am

The top routine works. The bottom routine doesn't. If you use them together, then you disable the OS routines entirely and the joystick will cease to work. The keyboard will kind-of work but very unreliably (and will lock up at the slightest provocation).

The IKBD communicates with the CPU via a serial protocol, communicated via the ACIA located at $fffc00/02. This is NOT individual keyboard data bytes. It consists of command packets that vary from 1 to about 5 or 6 bytes in length. In order to parse these you need a state machine which remembers what packet it's currently parsing. In pseudocode:

Code: Select all

if (state == no_packet)
{
  if (byte >= $f6)
    start_packet();
  else if (byte & 0x80)
    set_key_bit()
  else
    reset_key_bit();
}
else if (state == joystick_packet)
{
  joy[index++] = byte;
  if (index == 2) state = no_packet;
}
else if (state == mouse_packet)
{
   ...
} else ...

In addition, it's important - particularly if you have substantial raster effect routines - that before you exit the ACIA IRQ you check to see if the interrupt bit is set in $fffc00 and loop if so. Otherwise you will never see another interrupt and the keyboard will lock up.

If you want to reduce interference between the keyboard and Timer B, then all you need to do is move.w #$2500,sr as the first thing in your interrupt routine. Then the higher priority Timer B interrupt can interrupt the lower priority ACIA interrupt.

The simplest place to look at example code is the ST BIOS.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Mon Jul 15, 2013 8:14 am

Can you read all individual bytes by just reading fffc02 or do you need to do something else? I saw some example and he reloaded $118 with a new routine after he read each byte.
http://www.atari-forum.com/viewtopic.php?f=68&t=2768&p=215757&hilit=ikbd#p159209

I tried to use his routine but I didn't get anything in the "joy" variables so it did't work for me by some reason.
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Mon Jul 15, 2013 8:56 am

Nyh's method there is using the interrupt vector to manage the state machine. It's a valid method, although not without issues:
- the init code clobbers the existing MFP configuration fairly heavily, so if you use that unmodified other things will probably stop working
- I think it suffers the problem where if two bytes come through the ACIA very close together (but not close enough to trigger RX overrun) then it will lock the keyboard up
- I think it also requires AEI mode but I'm not sure I can see that being set up

You can't read bytes by just looking at fffc02 alone or there is always the lock-up risk. You have to check the RX interrupt bit in the control reg before returning (and handle buffer overrun as well, for the case where your program spends more than 1ms with interrupts disabled). And if you do read fffc02 directly you have to have a state machine to parse the packets.

The best example code is the ST BIOS disassembly, which does everything 'right', albeit overspecified for most game uses and not very efficiently.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Mon Jul 15, 2013 10:01 am

Ok, so I should check bit 0 in fffc00 first to see if there is anything here and if so, read fffc02 and if it's a keyboard code, just handle the value as it is, or if it's a joystick package, read fffc00 again to see if more is coming and fffc02 and so on....?

Where can I find the ST BIOS dissambly?
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

AtariZoll
Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 2978
Joined: Mon Feb 20, 2012 4:42 pm
Contact:

Re: IKBD Keyboard Joystick trouble

Postby AtariZoll » Mon Jul 15, 2013 11:18 am

I can post you disasm. of TOS 1.04 IKBD handler .
But before looking into it, you need to read some reliable doc. about IKBD protocol(s). For instance in Atari Compendium, or Atari ST ProfiBuch (german).
And yes, BIOS IKBD handler is not the fastest. If you want very fast, best is to look in some quality, not TOS using game with Steem Debugger. And beware that lot of games have crappy IKBD code :D
Famous Schrodinger's cat hypothetical experiment says that cat is dead or alive until we open box and see condition of poor animal, which deserved better logic. Cat is always in some certain state - regardless from is observer able or not to see what the state is.

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Mon Jul 15, 2013 11:39 am

Zamuel_a wrote:Ok, so I should check bit 0 in fffc00 first to see if there is anything here and if so, read fffc02 and if it's a keyboard code, just handle the value as it is, or if it's a joystick package, read fffc00 again to see if more is coming and fffc02 and so on....?

You can't do a waiting routine, unless you want to give up all your CPU time - keyboard bytes arrive about once every 1ms. You need a state machine that handles each incoming byte according to the current state of the machine. So you'd have states like 'keyboard or command byte' 'first joystick state' 'second joystick state' etc.

If I have time in the next couple of days I'll try to write up the parser in detail and give some example code. No promises though.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Mon Jul 15, 2013 12:37 pm

You can't do a waiting routine, unless you want to give up all your CPU time


Ah ofcourse! That wouldn't be so smart, hehe. But in general that's the procedure? I will give it a try and see what I can come up with. So all I need to do is to put my state machine at $118 and read fffc00 and fffc02? If a interrupt has occured, I don't understand why I should read fffc00 since that would just tell me what I already know? Reading fffc02 should be enought I guess.
Should I after my routine still jump to the old IKBD routine (as in my example) or replace it totally?
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Mon Jul 15, 2013 1:41 pm

You have to check fffc000. In fact, you have to check fffc004 as well. The interrupt on the MFP is edge-triggered, so if it stays low then the interrupt is not signalled again.

So, to give the simplest example, if you see an interrupt, read the keyboard, and do nothing else, and it's in fact a MIDI byte, then that's it, you've just seen your last ever keyboard interrupt. As I remember it there are race conditions where this can happen even with keyboard bytes (but I'll have to check more thoroughly to see what they are).

You can't chain IKBD interrupts. Once the byte's read from the ACIA it's gone.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Mon Jul 15, 2013 1:57 pm

I gave it a try and it seems to work! Rather simple after I understod how everything works.

This is my test:

Code: Select all

newikbd   move.w   d0,-(sp)

;   btst   #0,$fffffc00
;   beq   next2

   moveq.w   #0,d0
   move.b   $fffffc02.w,d0

   cmp.w   #0,ikbd_state
   beq.s   state_0
   cmp.w   #1,ikbd_state
   beq.s   joy0_1
   cmp.w   #2,ikbd_state
   beq.s   joy1_1
   bra   next

state_0   cmp.w   #$F6,d0      ;keyboard or something else?
   blt.s   keyb
   cmp.w   #$FE,d0      ;joystick 0 reporting
   beq.s   joy0_0
   cmp.w   #$FF,d0      ;joystick 1 reporting
   beq.s   joy1_0
   bra   next

joy0_0   move.w   #1,ikbd_state
   bra.s   next

joy1_0   move.w   #2,ikbd_state
   bra.s   next

joy0_1   move.b   d0,joy
   move.w   #0,ikbd_state
   bra.s   next

joy1_1   move.b   d0,joy+1
   move.w   #0,ikbd_state
   bra.s   next
   
keyb   movem.l   d1/a1,-(sp)

   lea   keyboard_buffer,a1

   move.b   d0,d1
   and.l   #$7F,d1
   adda.l   d1,a1   

   btst   #7,d0         ;check if it's a press or release
   bne.s   brkcode   
   move.b   #1,(a1)      
   movem.l   (sp)+,d1/a1
   bra.s   next
      
brkcode   move.b   #0,(a1)      
   movem.l   (sp)+,d1/a1
next   move.w   (sp)+,d0
next2
   dc.w   $4ef9
oldikbd   dc.l   0
   illegal


It seems to make no difference if I have the check at the beginning for fffc00, but maybe it should be here for safety? The mouse is disabled so that one shouldn't interfere with anything.
I guess the routine that sets $118 with a new address for each state is more efficent than mine since I have alot of compares, jumps in it.
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Mon Jul 15, 2013 2:50 pm

Zamuel_a wrote:I guess the routine that sets $118 with a new address for each state is more efficent than mine since I have alot of compares, jumps in it.

Yes. But it's only saving a couple of branches through a jump table, and as I noted, I'm not certain it's 100% reliable. (Jumptable methods can also be larger, and if space efficiency is key it may not always be a sensible tradeoff). There are worse inefficiencies than that in your code though. (e.g. testing the top bit doesn't need btst; you probably save at least one more register than required, clear more of d0 and d1 than required, etc.)

There's also a bug in your routine where it saves d0.w but uses moveq - moveq is always longword. Also, don't forget to clear the right bit in the ISR or the routine won't work in SEI mode.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Mon Jul 15, 2013 3:39 pm

testing the top bit doesn't need btst; you probably save at least one more register than required


You mean I should remove the test on fffc00 completely? I can't see a reason for it since it is inside the interrupt anyway, so no need to check if it has occured...?

Also, don't forget to clear the right bit in the ISR or the routine won't work in SEI mode.


Hmm, I'm not sure I understand completely. Isn't the interrupt itself keeping track of everything with the rte command or do I still need to do something manually?
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Mon Jul 15, 2013 5:18 pm

The MFP is a full interrupt controller. It has 16 interrupt priority levels each of which can be made pending and have interdependent priority even when other interrupts are in service.

The MFP IER controls interrupt enable. If that bit is 0, interrupts on the channel are ignored. Otherwise, when an interrupt edge transition is detected, the IPR bit is set by the MFP. The IMR is the mask register, which controls interrupt signalling; the MFP INT line is signalled if (IPR & IMR) != 0. During an interrupt acknowledge cycle, the MFP selects the vector based on the highest set bit in (IPR & IMR). That interrupt begins: the vector is sent to the 68000 by the standard iack protocol and the ISR bit is set.

There are then two modes: in SEI mode (the default) the priority system prevents the same or a lower priority interrupt occurring during the interrupt service routine, by not signalling interrupts where the signalled interrupt has lower priority than the highest set bit in the ISR. In AEI mode, the ISR bit is never set and so this system doesn't operate.

So at the end of a keyboard interrupt, you have to clear bit 6 of fffa11 (which doesn't need to be an RMW operation, 1 bits written are ignored, so simply write $bf to $fffa11).

As to why read fffc00 - well, if bit 7 and bit 0 aren't both set then there's no valid data to read. But yes, you may get away without this.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Tue Jul 16, 2013 8:13 am

Thanks for all the information! Is it necessary to write to fffa11 if my routine just hooks on to the normal IKBD routine? Maybe its not so good to hook it to that one at all so better do everything myself?
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Tue Jul 16, 2013 11:16 am

If you're using the BIOS routine to just hook joystick control then you don't need to worry about anything beyond writing d0 where you want it to go.

If you're doing anything with the ACIA and MFP directly then you have to do it all and cut the BIOS out. There's no way to have two different systems talking to the hardware.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Tue Jul 16, 2013 1:32 pm

The routine I wrote here is put in before the existing IKBD and jumps to that one at the end. It seems to work, but maybe it's not reliable.

Is there a good way to disable the IKBD interrupts to make sure they can't interfere with for example border removal and such critical tasks? In the past I did it with the "move.b #$13,$fffffc02.w" command for OFF and writing $11 to turn it back ON again. That worked, but with many key / joystick movements it hanged. I guess the IKBD buffer got full so it didn't send anything anymore or something. On my MEGA STE I had to disconnect the keyboard and plug it back in again so the IKBD got reseted and it started to work again.
Maybe there is a more reliable way to turn on, off the IKBD so it can only generate interrupts when I want it to.

EDIT:

I removed the "hook onto the old IKBD" code and now the routine didn't work, so I put in the "move.b "$bf,$fffa1" at the end and now everything seems to work fine!

The amount of code to handle the joysticks are not much more than seting up the XBIOS routine and it feels better to know what is going on :D

This is the "final" code after some optimizations.

Code: Select all

newikbd   move.w   d0,-(sp)

   move.w   sr,d0
   and.w   #$f8ff,d0
   or.w   #$500,d0
   move.w   d0,sr

   move.w   #0,d0
   move.b   $fffffc02.w,d0      ;read data from IKBD

   cmp.w   #0,ikbd_state
   beq.s   state_0
   cmp.w   #1,ikbd_state
   beq.s   joy0_1
   cmp.w   #2,ikbd_state
   beq.s   joy1_1
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

state_0   cmp.w   #$f6,d0         ;keyboard or something else?
   blt.s   keyb
   cmp.w   #$fe,d0         ;joystick 0 reporting
   beq.s   joy0_0
   cmp.w   #$ff,d0         ;joystick 1 reporting
   beq.s   joy1_0
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

joy0_0   move.w   #1,ikbd_state
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

joy1_0   move.w   #2,ikbd_state
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

joy0_1   move.b   d0,joy
   move.w   #0,ikbd_state
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

joy1_1   move.b   d0,joy+1
   move.w   #0,ikbd_state
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte
   
keyb   move.l   a1,-(sp)
   lea   keyboard_buffer,a1
   btst   #7,d0         ;check if it's a press or release
   bne.s   brkcode   
   move.b   #1,(a1,d0.w)      
   move.l   (sp)+,a1
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte
      
brkcode   and.w   #$7f,d0
   move.b   #0,(a1,d0.w)      
   move.l   (sp)+,a1
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

ikbd_state   dc.w   0
joy      ds.b   2
keyboard_buffer   ds.b   128


I'm not sure about the first 4 lines to lower the interrupt priority (just keept them from the previous routine). Seems strange to keep it inside the actual IRQ routine, since the interrupt already has happened, so I don't think this is the right way of doing this.
D0 is only handled as a word and that works, BUT the keyboard buffer must start on a even 16 bit boundary (or 8 bit since I'm only using 128 bytes) so that the adress never pass a 16 bit boundary, but I'm not sure how I can force the address start position in Devpac? Maybe a (a1,d0.w) instruction takes care of that itself? d0.l seems safer, but is ofcourse abit slower.
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Tue Jul 16, 2013 4:07 pm

Zamuel_a wrote:I removed the "hook onto the old IKBD" code and now the routine didn't work, so I put in the "move.b "$bf,$fffa1" at the end and now everything seems to work fine!

Right, that's all the OS routine was doing for you. You have to clear that ISR bit or you'll never see another ACIA interrupt.

I'm not sure about the first 4 lines to lower the interrupt priority (just keept them from the previous routine). Seems strange to keep it inside the actual IRQ routine, since the interrupt already has happened, so I don't think this is the right way of doing this.

The interrupt has already happened. But other MFP interrupts may want to happen - for example, Timer B interrupts for rasters. If you don't lower the IRQ priority, then your worst-case timer B interrupt delay is the entire cost of your interrupt routine, rather than a worst case of 50 cycles or so. (This is why many demos don't use the IRQ interrupt, even though testing less than once per ms runs the risk of lost data).

It's overkill to do the move-d0, and etc. though. Just move.w #$2500,sr (as the very first instruction) will do the job just fine. You're going to restore SP at the end of the routine, it doesn't matter how you change it inside.

Maybe a (a1,d0.w) instruction takes care of that itself? d0.l seems safer, but is ofcourse abit slower.

Yes, it does. A .W index is sign-extended to .L before addition, so with A1 = 0xffff, d0 = 2, it will quite happily write to 0x10001. This isn't a 6502 :D .

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Tue Jul 16, 2013 9:44 pm

I tested to reload $118 for each state instead of keeping track of it with a variable and when I compared this with the previous version, this way was much faster. I also reorganized the data alittle so it got abit faster. I have tried this on different emulators and real machines and it works without any problems what I could see. It ONLY treats joystick and keyboard commands so it's only intended for games.

Code: Select all

default_ikbd

   move.w   d0,-(sp)
   move.w   #$2500,sr
   move.b   $fffffc02.w,d0      ;read data from IKBD
   cmp.b   #$fe,d0         ;joystick 0 reporting
   beq   joy00
   cmp.b   #$ff,d0         ;joystick 1 reporting
   beq   joy10
   move.l   a1,-(sp)
   lea   keyboard_buffer,a1
   and.w   #$ff,d0
   btst   #7,d0         ;check if it's a press or release
   bne.s   brkcode   
   move.b   #1,(a1,d0.w)      
   move.l   (sp)+,a1
   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   rte

joy00   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   move.l   #joy01,$118
   rte

joy10   move.w   (sp)+,d0
   move.b   #$bf,$fffffa11
   move.l   #joy11,$118
   rte

joy01   move.w   #$2500,sr
   move.b   $fffffc02.w,joy      ;read data from IKBD
   move.b   #$bf,$fffffa11
   move.l   #default_ikbd,$118
   rte

joy11   move.w   #$2500,sr
   move.b   $fffffc02.w,joy+1   ;read data from IKBD
   move.b   #$bf,$fffffa11
   move.l   #default_ikbd,$118
   rte

keyboard_buffer   ds.b   128

joy      ds.b   2
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Wed Jul 17, 2013 10:44 am

The ISR bit should be cleared immediately before the RTE, not before setting $118, or there's a possible race there.

You can also add a lot of .w to your fffffa11s and $118s for additional speedups and smaller code.

Also be aware that the keyboard will lock if you ever receive a byte via midi and there are probably race cases where it can if you disable interrupts (or have higher priority interrupt in service continuously) for 1ms or more. Other than that it looks good.

Zamuel_a
Atari God
Atari God
Posts: 1235
Joined: Wed Dec 19, 2007 8:36 pm
Location: Sweden

Re: IKBD Keyboard Joystick trouble

Postby Zamuel_a » Wed Jul 17, 2013 10:55 am

I tried to set the new address to $118 before setting the ISR bit but it didn't work on a real machine! It looked up after the first jostick input. It works on emulators but not in real. After I moved it like it is now everything seems to work fine.

It's supposed to be used for games only, so midi shouldn't be available, but if it's possible to disable the midi ports, it had been good.
ST / STFM / STE / Mega STE / Falcon / TT030 / Portfolio / 2600 / 7800 / Jaguar / 600xl / 130xe

Dio
Captain Atari
Captain Atari
Posts: 451
Joined: Thu Feb 28, 2008 3:51 pm

Re: IKBD Keyboard Joystick trouble

Postby Dio » Wed Jul 17, 2013 12:56 pm

Good point. You could probably write 3 to FFFFFC04, which would lock the MIDI ACIA off.

I am somewhat concerned that the code should care about the order of those two operations. Does it work the other way around if you leave out the move to SR?

User avatar
Nyh
Atari God
Atari God
Posts: 1496
Joined: Tue Oct 12, 2004 2:25 pm
Location: Netherlands

Re: IKBD Keyboard Joystick trouble

Postby Nyh » Tue Jul 23, 2013 10:53 am

I am sorry but I didn't read the whole thread but this is my keyborad/mouse/joystick handling routine:

Code: Select all

;
; keyboard interrupt handler
; (c) 1997 Mr Ni! the Great
;
; Geeft de volgende informatie:
; mouse_x:  dc.w   0     ;  volatile int mouse_x;
; mouse_y:  dc.w   0     ;  volatile int mouse_y;
; click_x:  dc.w   0     ;  volatile int click_x;
; click_y:  dc.w   0     ;  volatile int click_y;
; buttons:  dc.b   0     ;  volatile char buttons;
; click_f:  dc.b   0     ;  volatile char click_f; /* flag shows buttons that caused the click */
; joy0:     dc.b   0     ;  volatile byte joy0;
; joy1:     dc.b   0     ;  volatile byte joy1;
; joy2:     dc.b   0     ;  volatile byte joy2; /* cursor joystick */
; last_key: dc.b   0     ;  volatile byte last_key;
;

EXPORT key_info
EXPORT key_interrupt
EXPORT initmuis          ; void initmuis(void)
EXPORT showmuis          ; void showmuis(int x, int y, void* screen)
EXPORT hidemuis          ; void hidemuis(void)

                TEXT

JOY_UP    equ 1
JOY_LEFT  equ 4
JOY_RIGHT equ 8
JOY_DOWN  equ 2
JOY_FIRE  equ $80

;MOUSE_X_MIN equ 0   implicit zero check
MOUSE_X_MAX equ 319
;MOUSE_Y_MIN equ 0   implicit zero check
MOUSE_Y_MAX equ 199

;/* key handeler info */
;struct key_handler_info_struct
key_info:
mouse_x:  dc.w   MOUSE_X_MAX/2     ;  volatile int mouse_x;
mouse_y:  dc.w   MOUSE_Y_MAX/2     ;  volatile int mouse_y;
click_x:  dc.w   0     ;  volatile int click_x;
click_y:  dc.w   0     ;  volatile int click_y;
buttons:  dc.b   0     ;  volatile char buttons;
click_f:  dc.b   0     ;  volatile char click_f; /* flag shows buttons that caused the click */
joy0:     dc.b   0     ;  volatile byte joy0;
joy1:     dc.b   0     ;  volatile byte joy1;
joy2:     dc.b   0     ;  volatile byte joy2; /* cursor joystick */
last_key: dc.b   0     ;  volatile byte last_key;
old_b:    dc.b   0     ;  last button state
.even

key_interrupt:
     move.w    d0,-(sp)          ;
     clr.w     d0                ; clear register
     move.b    $fffffc02.w,d0    ; get scancode
     add.w     d0,d0             ; verdubbel keycode
     move.w    .table_start(pc,d0.w),d0; get jump offset
     jmp       .table_start(pc,d0.w)

.table_start:
     dc.w      .default-.table_start ;00
     dc.w      .default-.table_start ;01
     dc.w      .default-.table_start ;02
     dc.w      .default-.table_start ;03
     dc.w      .default-.table_start ;04
     dc.w      .default-.table_start ;05
     dc.w      .default-.table_start ;06
     dc.w      .default-.table_start ;07
     dc.w      .default-.table_start ;08
     dc.w      .default-.table_start ;09
     dc.w      .default-.table_start ;0a
     dc.w      .default-.table_start ;0b
     dc.w      .default-.table_start ;0c
     dc.w      .default-.table_start ;0d
     dc.w      .default-.table_start ;0e
     dc.w      .default-.table_start ;0f
     dc.w      .default-.table_start ;10
     dc.w      .default-.table_start ;11
     dc.w      .default-.table_start ;12
     dc.w      .default-.table_start ;13
     dc.w      .default-.table_start ;14
     dc.w      .default-.table_start ;15
     dc.w      .default-.table_start ;16
     dc.w      .default-.table_start ;17
     dc.w      .default-.table_start ;18
     dc.w      .default-.table_start ;19
     dc.w      .default-.table_start ;1a
     dc.w      .default-.table_start ;1b
     dc.w      .default-.table_start ;1c
     dc.w      .default-.table_start ;1d
     dc.w      .default-.table_start ;1e
     dc.w      .default-.table_start ;1f
     dc.w      .default-.table_start ;20
     dc.w      .default-.table_start ;21
     dc.w      .default-.table_start ;22
     dc.w      .default-.table_start ;23
     dc.w      .default-.table_start ;24
     dc.w      .default-.table_start ;25
     dc.w      .default-.table_start ;26
     dc.w      .default-.table_start ;27
     dc.w      .default-.table_start ;28
     dc.w      .default-.table_start ;29
     dc.w      .default-.table_start ;2a
     dc.w      .default-.table_start ;2b
     dc.w      .default-.table_start ;2c
     dc.w      .default-.table_start ;2d
     dc.w      .default-.table_start ;2e
     dc.w      .default-.table_start ;2f
     dc.w      .default-.table_start ;30
     dc.w      .default-.table_start ;31
     dc.w      .default-.table_start ;32
     dc.w      .default-.table_start ;33
     dc.w      .default-.table_start ;34
     dc.w      .default-.table_start ;35
     dc.w      .default-.table_start ;36
     dc.w      .default-.table_start ;37
     dc.w      .default-.table_start ;38
     dc.w      .cur_fire_p-.table_start ;39
     dc.w      .default-.table_start ;3a
     dc.w      .default-.table_start ;3b
     dc.w      .default-.table_start ;3c
     dc.w      .default-.table_start ;3d
     dc.w      .default-.table_start ;3e
     dc.w      .default-.table_start ;3f
     dc.w      .default-.table_start ;40
     dc.w      .default-.table_start ;41
     dc.w      .default-.table_start ;42
     dc.w      .default-.table_start ;43
     dc.w      .default-.table_start ;44
     dc.w      .default-.table_start ;45
     dc.w      .default-.table_start ;46
     dc.w      .default-.table_start ;47
     dc.w      .cur_up_p-.table_start ;48
     dc.w      .default-.table_start ;49
     dc.w      .default-.table_start ;4a
     dc.w      .cur_left_p-.table_start ;4b
     dc.w      .default-.table_start ;4c
     dc.w      .cur_right_p-.table_start ;4d
     dc.w      .default-.table_start ;4e
     dc.w      .default-.table_start ;4f
     dc.w      .cur_down_p-.table_start ;50
     dc.w      .default-.table_start ;51
     dc.w      .default-.table_start ;52
     dc.w      .default-.table_start ;53
     dc.w      .default-.table_start ;54
     dc.w      .default-.table_start ;55
     dc.w      .default-.table_start ;56
     dc.w      .default-.table_start ;57
     dc.w      .default-.table_start ;58
     dc.w      .default-.table_start ;59
     dc.w      .default-.table_start ;5a
     dc.w      .default-.table_start ;5b
     dc.w      .default-.table_start ;5c
     dc.w      .default-.table_start ;5d
     dc.w      .default-.table_start ;5e
     dc.w      .default-.table_start ;5f
     dc.w      .default-.table_start ;60
     dc.w      .default-.table_start ;61
     dc.w      .default-.table_start ;62
     dc.w      .default-.table_start ;63
     dc.w      .default-.table_start ;64
     dc.w      .default-.table_start ;65
     dc.w      .default-.table_start ;66
     dc.w      .default-.table_start ;67
     dc.w      .default-.table_start ;68
     dc.w      .default-.table_start ;69
     dc.w      .default-.table_start ;6a
     dc.w      .default-.table_start ;6b
     dc.w      .default-.table_start ;6c
     dc.w      .default-.table_start ;6d
     dc.w      .default-.table_start ;6e
     dc.w      .default-.table_start ;6f
     dc.w      .default-.table_start ;70
     dc.w      .default-.table_start ;71
     dc.w      .default-.table_start ;72
     dc.w      .default-.table_start ;73
     dc.w      .default-.table_start ;74
     dc.w      .default-.table_start ;75
     dc.w      .default-.table_start ;76
     dc.w      .default-.table_start ;77
     dc.w      .default-.table_start ;78
     dc.w      .default-.table_start ;79
     dc.w      .default-.table_start ;7a
     dc.w      .default-.table_start ;7b
     dc.w      .default-.table_start ;7c
     dc.w      .default-.table_start ;7d
     dc.w      .default-.table_start ;7e
     dc.w      .default-.table_start ;7f
     dc.w      .default-.table_start ;80
     dc.w      .default-.table_start ;81
     dc.w      .default-.table_start ;82
     dc.w      .default-.table_start ;83
     dc.w      .default-.table_start ;84
     dc.w      .default-.table_start ;85
     dc.w      .default-.table_start ;86
     dc.w      .default-.table_start ;87
     dc.w      .default-.table_start ;88
     dc.w      .default-.table_start ;89
     dc.w      .default-.table_start ;8a
     dc.w      .default-.table_start ;8b
     dc.w      .default-.table_start ;8c
     dc.w      .default-.table_start ;8d
     dc.w      .default-.table_start ;8e
     dc.w      .default-.table_start ;8f
     dc.w      .default-.table_start ;90
     dc.w      .default-.table_start ;91
     dc.w      .default-.table_start ;92
     dc.w      .default-.table_start ;93
     dc.w      .default-.table_start ;94
     dc.w      .default-.table_start ;95
     dc.w      .default-.table_start ;96
     dc.w      .default-.table_start ;97
     dc.w      .default-.table_start ;98
     dc.w      .default-.table_start ;99
     dc.w      .default-.table_start ;9a
     dc.w      .default-.table_start ;9b
     dc.w      .default-.table_start ;9c
     dc.w      .default-.table_start ;9d
     dc.w      .default-.table_start ;9e
     dc.w      .default-.table_start ;9f
     dc.w      .default-.table_start ;a0
     dc.w      .default-.table_start ;a1
     dc.w      .default-.table_start ;a2
     dc.w      .default-.table_start ;a3
     dc.w      .default-.table_start ;a4
     dc.w      .default-.table_start ;a5
     dc.w      .default-.table_start ;a6
     dc.w      .default-.table_start ;a7
     dc.w      .default-.table_start ;a8
     dc.w      .default-.table_start ;a9
     dc.w      .default-.table_start ;aa
     dc.w      .default-.table_start ;ab
     dc.w      .default-.table_start ;ac
     dc.w      .default-.table_start ;ad
     dc.w      .default-.table_start ;ae
     dc.w      .default-.table_start ;af
     dc.w      .default-.table_start ;b0
     dc.w      .default-.table_start ;b1
     dc.w      .default-.table_start ;b2
     dc.w      .default-.table_start ;b3
     dc.w      .default-.table_start ;b4
     dc.w      .default-.table_start ;b5
     dc.w      .default-.table_start ;b6
     dc.w      .default-.table_start ;b7
     dc.w      .default-.table_start ;b8
     dc.w      .cur_fire_r-.table_start ;b9
     dc.w      .default-.table_start ;ba
     dc.w      .default-.table_start ;bb
     dc.w      .default-.table_start ;bc
     dc.w      .default-.table_start ;bd
     dc.w      .default-.table_start ;be
     dc.w      .default-.table_start ;bf
     dc.w      .default-.table_start ;c0
     dc.w      .default-.table_start ;c1
     dc.w      .default-.table_start ;c2
     dc.w      .default-.table_start ;c3
     dc.w      .default-.table_start ;c4
     dc.w      .default-.table_start ;c5
     dc.w      .default-.table_start ;c6
     dc.w      .default-.table_start ;c7
     dc.w      .cur_up_r-.table_start ;c8
     dc.w      .default-.table_start ;c9
     dc.w      .default-.table_start ;ca
     dc.w      .cur_left_r-.table_start ;cb
     dc.w      .default-.table_start ;cc
     dc.w      .cur_right_r-.table_start ;cd
     dc.w      .default-.table_start ;ce
     dc.w      .default-.table_start ;cf
     dc.w      .cur_down_r-.table_start ;d0
     dc.w      .default-.table_start ;d1
     dc.w      .default-.table_start ;d2
     dc.w      .default-.table_start ;d3
     dc.w      .default-.table_start ;d4
     dc.w      .default-.table_start ;5d
     dc.w      .default-.table_start ;d6
     dc.w      .default-.table_start ;d7
     dc.w      .default-.table_start ;d8
     dc.w      .default-.table_start ;d9
     dc.w      .default-.table_start ;da
     dc.w      .default-.table_start ;db
     dc.w      .default-.table_start ;dc
     dc.w      .default-.table_start ;dd
     dc.w      .default-.table_start ;de
     dc.w      .default-.table_start ;df
     dc.w      .default-.table_start ;e0
     dc.w      .default-.table_start ;e1
     dc.w      .default-.table_start ;e2
     dc.w      .default-.table_start ;e3
     dc.w      .default-.table_start ;e4
     dc.w      .default-.table_start ;e5
     dc.w      .default-.table_start ;e6
     dc.w      .default-.table_start ;e7
     dc.w      .default-.table_start ;e8
     dc.w      .default-.table_start ;e9
     dc.w      .default-.table_start ;ea
     dc.w      .default-.table_start ;eb
     dc.w      .default-.table_start ;ec
     dc.w      .default-.table_start ;ed
     dc.w      .default-.table_start ;ee
     dc.w      .default-.table_start ;ef
     dc.w      .default-.table_start ;f0
     dc.w      .default-.table_start ;f1
     dc.w      .default-.table_start ;f2
     dc.w      .default-.table_start ;f3
     dc.w      .default-.table_start ;f4
     dc.w      .default-.table_start ;f5
     dc.w      .default-.table_start ;f6
     dc.w      .default-.table_start ;f7
     dc.w      .mouse_0-.table_start ;f8
     dc.w      .mouse_1-.table_start ;f9
     dc.w      .mouse_2-.table_start ;fa
     dc.w      .mouse_3-.table_start ;fb
     dc.w      .default-.table_start ;fc
     dc.w      .default-.table_start ;fd
     dc.w      .new_joy0-.table_start ;fe
     dc.w      .new_joy1-.table_start ;ff

; key action code
.default:
     move.b    $fffffc02.w,last_key; store last key
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.new_joy0:
     move.l    #.get_joy0,$118.w
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.new_joy1:
     move.l    #.get_joy1,$118.w
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.mouse_0:
     clr.b     buttons           ; no buttons
     move.l    #.get_mouse_x,$118.w; get mouse_x
     move.w    (sp)+,d0
     move.b    #$bf,$fffffa11.w
     rte
.mouse_1:
     move.b    #1,buttons        ; right button
     move.l    #.get_mouse_x,$118.w; get mouse_x
     move.w    (sp)+,d0
     move.b    #$bf,$fffffa11.w
     rte
.mouse_2:
     move.b    #2,buttons        ; left button
     move.l    #.get_mouse_x,$118.w; get mouse_x
     move.w    (sp)+,d0
     move.b    #$bf,$fffffa11.w
     rte
.mouse_3:
     move.b    #3,buttons        ; both buttons
     move.l    #.get_mouse_x,$118.w; get mouse_x
     move.w    (sp)+,d0
     move.b    #$bf,$fffffa11.w
     rte

.get_joy0:
     move.b    $fffffc02.w,joy0  ; get joy0 status
     move.l    #key_interrupt,$118.w
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.get_joy1:
     move.b    $fffffc02.w,joy1  ; get joy1 status
     move.l    #key_interrupt,$118.w
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.get_mouse_x:
     move.w    d0,-(sp)
     clr.w     d0
     move.b    $fffffc02.w,d0    ; coordinate
     ext.w     d0
     add.w     mouse_x(pc),d0    ; new mouse_x
     bge.s     .mouse_x_max
     clr.w     d0
     bra.s     .mouse_x_done
.mouse_x_max:
     cmp.w     #MOUSE_X_MAX,d0
     ble.s     .mouse_x_done
     move.w    #MOUSE_X_MAX,d0
.mouse_x_done:
     move.w    d0,mouse_x
     move.l    #.get_mouse_y,$118.w; get mouse_y
     move.w    (sp)+,d0
     move.b    #$bf,$fffffa11.w
     rte
.get_mouse_y:
     move.l    #key_interrupt,$118.w;
     move.w    d0,-(sp)
     move.l    a0,-(sp)
     lea       old_b(pc),a0
     clr.w     d0
     move.b    $fffffc02.w,d0    ; coordinate
     ext.w     d0
     add.w     mouse_y-old_b(a0),d0 ; new mouse_y
     bge.s     .mouse_y_max
     clr.w     d0
     bra.s     .mouse_ytest_done
.mouse_y_max:
     cmp.w     #MOUSE_Y_MAX,d0
     ble.s     .mouse_ytest_done
     move.w    #MOUSE_Y_MAX,d0
.mouse_ytest_done:
     move.w    d0,mouse_y-old_b(a0)
     clr.w     d0
     move.b    (a0),d0           ; old button state
     add.w     d0,d0
     add.w     d0,d0
     or.b      buttons-old_b(a0),d0
     move.b    buttons-old_b(a0),(a0)
     move.b    .click_tab(d0.w,pc),d0 ; is there a click?
     beq.s     .mouse_y_done
     move.b    d0,click_f-old_b(a0)  ; set click flag
     move.w    mouse_x-old_b(a0),click_x-old_b(a0)
     move.w    mouse_y-old_b(a0),click_y-old_b(a0)
.mouse_y_done:
     move.l    (sp)+,a0
     move.w    (sp)+,d0
     move.b    #$bf,$fffffa11.w
     rte

.click_tab:
    dc.b 0,1,2,3,0,0,2,2,0,1,0,1,0,0,0,0 ; click table

.cur_up_p:
     or.b      #JOY_UP,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_up_r:
     and.b     #!JOY_UP,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_left_p:
     or.b      #JOY_LEFT,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_left_r:
     and.b     #!JOY_LEFT,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_right_p:
     or.b      #JOY_RIGHT,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_right_r:
     and.b     #!JOY_RIGHT,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_down_p:
     or.b      #JOY_DOWN,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_down_r:
     and.b     #!JOY_DOWN,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_fire_p:
     or.b      #JOY_FIRE,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done
.cur_fire_r:
     and.b     #$7f,joy2
     move.w    (sp)+,d0          ; restore registers
     move.b    #$bf,$fffffa11.w
     rte                         ; done

initmuis:                        ; preshift muis data
     move.l    d3,-(sp)
     lea       muisdata(pc),a0
     lea       muispreshift+(15*256)+16,a1
     moveq     #15,d0
.lineloop:
     moveq     #-1,d1
     moveq     #0,d2
     move.w    (a0)+,d1          ; mask
     move.w    (a0)+,d2          ; data
     moveq     #15,d3
.shiftloop:
     add.l     d1,d1
     addq.w    #1,d1
     add.l     d2,d2
     move.w    d2,-(a1)
     move.w    d2,-(a1)
     move.w    d1,-(a1)
     move.w    d1,-(a1)
     swap      d2
     swap      d1
     move.w    d2,-(a1)
     move.w    d2,-(a1)
     move.w    d1,-(a1)
     move.w    d1,-(a1)
     swap      d2
     swap      d1
     lea       -256+16(a1),a1
     dbra      d3,.shiftloop
     lea       (16*256)+16(a1),a1
     dbra      d0,.lineloop
     move.l    (sp)+,d3
     rts

hidemuis:
     lea       muisbuffer,a0
     move.l    (a0)+,a1
     move.w    (a0)+,d0            ; lines
     move.w    (a0)+,d1            ; words
     bne.s     .singlelong
     movem.l   d3-d4,-(sp)
.lineloop0:
     movem.l   (a0)+,d1-d4
     movem.l   d1-d4,(a1)
     lea       160(a1),a1
     dbra      d0,.lineloop0
     movem.l   (sp)+,d3-d4
     rts
.singlelong:
.lineloop1:
     move.l    (a0)+,(a1)+
     move.l    (a0)+,(a1)+
     lea       160-8(a1),a1
     dbra      d0,.lineloop1
     rts


; d0.w x
; d1.w y
; a0 screen
showmuis:
     movem.l   d3-d6/a2,-(sp)
     move.w    #MOUSE_Y_MAX,d2
     sub.w     d1,d2      ; lines
     cmp.w     #15,d2     ; #lines
     bls.s     .nolinefix
     moveq     #15,d2     ; max 16 lines
.nolinefix:
     mulu      #160,d1    ; y-offset
     moveq     #-16,d3
     and.w     d0,d3
     lsr.w     #1,d3      ; x-offset
     add.w     d1,d3      ; offset muisdata
     lea       0(d3.w,a0),a0
     lea       muisbuffer,a1
     move.l    a0,(a1)+
     move.w    d2,(a1)+
     cmp.w     #MOUSE_X_MAX-16,d0
     bgt.s     .singleword
     clr.w     (a1)+
     move.w    d2,d1
     move.l    a0,a2
.lineloop0:
     movem.l   (a2),d3-d6
     movem.l   d3-d6,(a1)
     lea       160(a2),a2
     lea       16(a1),a1
     dbra      d2,.lineloop0
     and.w     #$f,d0
     lsl.w     #8,d0      ; offset in preshiftdata
     lea       muispreshift,a1
     add.w     d0,a1
.tekenloop0:
     movem.l   (a1)+,d2/d3/d4/d5
     move.l    (a0)+,d0
     and.l     d2,d0
     or.l      d3,d0
     and.l     (a0)+,d2
     or.l      d3,d2
     move.l    (a0)+,d3
     and.l     d4,d3
     or.l      d5,d3
     and.l     (a0)+,d4
     or.l      d5,d4
     movem.l   d0/d2-d4,-(a0)
     lea       160(a0),a0
     dbra      d1,.tekenloop0
     movem.l   (sp)+,d3-d6/a2
     rts

.singleword:
     move.w    d0,(a1)+               ; set word flag
     move.w    d2,d1
     move.l    a0,a2
.lineloop1:
     move.l    (a2)+,(a1)+
     move.l    (a2)+,(a1)+
     lea       160-8(a2),a2
     dbra      d2,.lineloop1
     and.w     #$f,d0
     lsl.w     #8,d0      ; offset in preshiftdata
     lea       muispreshift,a1
     add.w     d0,a1
.tekenloop1:
     move.l    (a1)+,d2
     move.l    (a1)+,d3
     move.l    (a0)+,d0
     and.l     d2,d0
     or.l      d3,d0
     and.l     (a0)+,d2
     or.l      d3,d2
     movem.l   d0/d2,-(a0)
     lea       160(a0),a0
     addq.l    #8,a1
     dbra      d1,.tekenloop1
     movem.l   (sp)+,d3-d6/a2
     rts

     
     

muisdata:
dc.b 63,255,0,0,31,255,64,0,15,255,96,0,7,255,112,0
dc.b 3,255,120,0,1,255,124,0,0,255,126,0,0,127,127,0
dc.b 0,63,127,128,0,31,124,0,1,255,108,0,16,255,70,0
dc.b 48,255,6,0,120,127,3,0,248,127,3,0,248,127,0,0

BSS

muisbuffer:
     ds.l 1                       ; screenpos of mouse data
     ds.w 1                       ; # lines
     ds.w 1                       ; 1 word?
     ds.b 16*16                   ; schermdata
muispreshift:
     ds.b 16*256                  ; mask mask data data mask mask data data; newline


Social Media

     

Return to “680x0”

Who is online

Users browsing this forum: No registered users and 3 guests