Grauw’s RPG in development

페이지 11/22
4 | 5 | 6 | 7 | 8 | 9 | 10 | | 12 | 13 | 14 | 15 | 16

By DarkSchneider

Paladin (890)

DarkSchneider의 아바타

05-04-2018, 08:11

@Grauw are you reading the keyboard from NEWKEY system variable? The BIOS already reads keyboard state and stores the row values into NEWKEY array. You don't even need to call the BIOS keyboard functions.
But don't use OLDKEY for comparing, copy NEWKEY to your own array after reading it. Seems OLDKEY does not work (at least for me) as intended, but also is not correct to use it, as we need to compare with our previous frame logic, not with the previous interrupt state.

Other concernings about the BIOS, remember that a MSX could be made in many ways, as open architecture, it usually has 8 internal sub-slots, with anything connected to them. It could be that a manufacturer connected something and updates it at the 0038h routine, just like the PAUSE button on the Panasonic.
Look at the 0038h just like the system ISR, that should be called except maybe on cartridge software.

Then I think the safer thing is: doing everything you need at your IM2 ISR, and then set S#0 and call 0038h. If want you could at return of 0038h set S#2 before RETI.

There is a big difference compared to using IM1 in any case. IM1 mode always calls 0038h so it uses inter-slot many times (once per interrupt). Using IM2 you 1st check if the interrupt is for your ISR (checking S#1 for line interrupt) and if it is, you dispatch it and RETI, not calling 0038h.

By Grauw

Ascended (8617)

Grauw의 아바타

05-04-2018, 08:55

DarkSchneider wrote:

@Grauw are you reading the keyboard from NEWKEY system variable? The BIOS already reads keyboard state and stores the row values into NEWKEY array. You don't even need to call the BIOS keyboard functions.
But don't use OLDKEY for comparing, copy NEWKEY to your own array after reading it.

Yep, that's exactly what I did. And I haven't even increased the scanning frequency to once every interrupt...

DarkSchneider wrote:

Then I think the safer thing is: doing everything you need at your IM2 ISR, and then set S#0 and call 0038h. If want you could at return of 0038h set S#2 before RETI.

Yeah that's going to have to be the plan. Plus a guard flag to deal with the enabled ints after 38H returns. (Btw, RETI is not used on MSX, just RET.)

DarkSchneider wrote:

There is a big difference compared to using IM1 in any case. IM1 mode always calls 0038h so it uses inter-slot many times (once per interrupt). Using IM2 you 1st check if the interrupt is for your ISR (checking S#1 for line interrupt) and if it is, you dispatch it and RETI, not calling 0038h.

Depends on the environment... in DOS it calls 38H in RAM, so it's much easier to hook in to than IM2. Benefit of IM2 on the other hand is that you can keep it in page 3 and it will still be called when the BIOS is paged in so it's safer to keep enabled while invoking BDOS or BIOS routines.

Currently I use the ROM environment though, although I'm still debating whether to change to the DOS environment. I will postpone the decision probably until I'm sure 64K of RAM will be enough for me.

By DarkSchneider

Paladin (890)

DarkSchneider의 아바타

05-04-2018, 11:09

Also consider using the BASIC system work area. It is a waste of valuable space at page 3. And while not in BASIC it is not used, and when BASIC boots it initializes their values (when required) so it can be used.

I think to remember about putting the IM2 ISR at page 3, requiring to create a larger stack space because the ABAB style memory address requirement (low = high).

Well, look at this:

Quote:

KBUF (F41FH, 318)
contents: crunch buffer; translated into intermediate language from
BUF (F55EH)

BUFMIN (F55DH, 1)
initial value: ","
contents: used in INPUT statement

BUF (F55EH, 258)
contents: buffer to store characters typed; where direct statements
are stored in ASCII code

Put the routine at F5F5h, 107 bytes of space, if not enough for ISR, simply put a JP to F41Fh at the end and continue there. That is a lot of space to be used.
Can even to reserve the exact space at stack, instead a larger one, an put a JP to that address at any ABAB address on the BASIC system work area.

Also, other spaces used by BASIC interpreter, while not active, could be used. Like the USR to store our own function pointers at page 3, or the "Data area used in PLAY statement" as our own sound working area.

Quote:

* Data area used in PLAY statement

MCLTAB (F956H, 2)
contents: points to the top of the table of PLAY macro or DRAW macro

MCLFLG (F958H, 1)
contents: assignment of PLAY/DRAW

QUETAB (F959H, 24)
contents: queue table
+0: PUT offset
+1: GET offset
+2: backup character
+3: queue length
+4: queue address
+5: queue address

QUEBAK (F971H, 4)
contents: used in BCKQ

VOICAQ (F975H, 128)
contents: queue of voice 1 (1 = a)

VOICBQ (F9F5H, 128)
contents: queue of voice 2 (2 = b)

VOICCQ (FA75H, 128)
contents: queue of voice 3 (3 = c)

So much space wasted.

By Grauw

Ascended (8617)

Grauw의 아바타

05-04-2018, 11:27

The play queue can be a good place to store stuff, but for that reason it’s also often used by TSRs, so I tend to ignore it. Either way, I currently don’t have a RAM shortage (only using RAM up to 0C586H), and if I do end up having one I could still investigate either swapping the BIOS out of page 0 (meh) or using the DOS environment.

By DarkSchneider

Paladin (890)

DarkSchneider의 아바타

05-04-2018, 11:56

Yes if using external libs simply avoid to collide. In any case is a lot of space at page 3, very valuable in a DOS environment because the ISR and its working area must be fit into page 3 as for other pages would need inter-slot as we don't know the slots state.

Another examples, the MSX-Music BIOS work area, put it on there so no need to slot change. And any other one we could think about it.

Not seen in detail yet, but if there is no other than BASIC interpreter work area within the range, it could be used even as a full contiguous space. Avoiding the external libs collision as said.

By sd_snatcher

Prophet (3135)

sd_snatcher의 아바타

05-04-2018, 20:01

Grauw wrote:
DarkSchneider wrote:

@Grauw are you reading the keyboard from NEWKEY system variable? The BIOS already reads keyboard state and stores the row values into NEWKEY array. You don't even need to call the BIOS keyboard functions.
But don't use OLDKEY for comparing, copy NEWKEY to your own array after reading it.

Yep, that's exactly what I did. And I haven't even increased the scanning frequency to once every interrupt...

I had to rewrite my answer, since I noticed I missed some messages in the thread.

I prefer to scan the keyboard exactly as Grauw had been doing: disable the block of the BIOS ISR that comes after the hook processing.

Then, from either HKEYI or HTIMI, I call SNSMAT to read only the keyboard rows that I need, and store them in variables in RAM. The main loop of the game will only read the button/keys state from those variables. This method looks and performs very similar to direct I/O, but replaces the OUTs with SNSMAT, and reduces the slowdown on turbo machines.

By Grauw

Ascended (8617)

Grauw의 아바타

05-04-2018, 20:26

With SNSMAT it is quite a bit faster than via the BIOS ISR, 1% slower than it is now, rather than 2.5%, and without latency problems. So I guess of the two that is the better way. And if the BIOS ISR’s key scanning is disabled via SCNCNT, writing the matrix data to NEWKEY and OLDKEY is probably also a good idea.

By DarkSchneider

Paladin (890)

DarkSchneider의 아바타

05-04-2018, 20:32

And how is disabled the keyboard scan on BIOS ISR? Setting the SCNCNT to 255 or 0?

By Grauw

Ascended (8617)

Grauw의 아바타

05-04-2018, 20:46

Like so:

https://bitbucket.org/grauw/tiletile/src/87ed317515/src/TIMI...

The interrupt decreases the values in SCNCNT (8-bit) and INTCNT (16-bit) every frame, and if reaches zero it will scan the keyboard and joysticks, trigger BASIC events, etc. When you set SCNCNT to 0 (=256) it will take over 4 seconds before it reaches the threshold. So you don’t necessarily need to set up a hook to reset them, you can do it on the main loop with a lesser frequency as well.

More details in the MSX Red Book or the disassembled BIOS code.

By sd_snatcher

Prophet (3135)

sd_snatcher의 아바타

05-04-2018, 22:38

If needed, there's a even faster approach than only setting SCNCNT to zero: as the very last instruction of your HKEYI routine, CALL RDVDP. This will clear the frame interrupt flag from the VDP status register and make sure that not even HTIMI and JIFFY are processed, and that the PSG queues aren't checked, leading to a much quicker exit.

You have to make sure that your HKEYI routine doesn't last longer than a frame though. Well, anyone should make sure that it doesn't ever take that long for any reason. The ISR is no place for huge processing.

Keep in mind that this approach is not friendly to any existing hook-installed extensions though. It's a trade-off that will deprive them from CPU access. But it will still be compatible with applications that capture BIOS calls, like the SofaRun suite.

페이지 11/22
4 | 5 | 6 | 7 | 8 | 9 | 10 | | 12 | 13 | 14 | 15 | 16