[MSX-C] Q&A official thread

Page 65/68
58 | 59 | 60 | 61 | 62 | 63 | 64 | | 66 | 67 | 68

By ducasp

Paladin (677)

ducasp's picture

07-02-2023, 15:24

rolandve wrote:

So how to use Jiffy. The system starts to behave erratic, like hang.

I have Jiffy defined as

#define Jiffy 	(*(unsigned *)0xFC9E)

while debugging I also defined Jiffy as

#define Jiffy 	(*(TINY *)0xfc9e)

But when I want to work with Jiffy, the system hangs, when I use it like below. It works exactly 1 time. Then the system hangs. Reset required.

 unsigned oldJiffy;
oldJiffy = Jiffy;
if ( Jiffy > (oldJiffy +10 ) ) {
update();
oldJiffy = Jiffy;
}

Taking out Jiffy, the systems loops extremely fast, so it's not the code itself. Why does using Jiffy hang a system?

Can't help you much on MSX C as I've never used it, I use SDCC instead, but your code is not optimized (perhaps the compiler will optimize it for you, perhaps not, but it is always best when you think optimized Cool ), in the If clause you are always adding 10 to oldJiffy, just make oldJiffy plain Jiffy + 10 and call it timer or something simillar, if Jiffy > Timer.... This will guarantee a plain comparison on the If clause instead of reading from memory, adding, then comparing...

Also, I would define a variable, myJiffy, as an unsigned int (whatever unsigned 16 bit type MSX C has) pointer, and then assign it the value of Jiffy address... With SDCC we have a neat trick that allows us to skip this altogether:

__at 0xFC9E unsigned int myJiffy;

This is very clean and optimized, not sure if your tries with @define and casting do the same on MSX C, perhaps it was not thought to use it that way...

By the way, there is a bug in this type o Jiffy usage and you can get imeddiate return several times when Jiffy is greater than FFF5, because the comparison will be FFF6 > 0, and until Jiffy goes back to 0 you will have this issue in your code... A nicer way to do would be to hook to 0xFD9F (VDP interrupts) to a simple function that will increase an internal counter of your own and in your code you check if count > 10, if so, reset count to 0 in your code and do your stuff... This way you won't have the overflow bug, and also won't have any issues if any device / software / driver / piece of bios reset JIFFY counter (some do, very sad, not a good practice) to guarantee it will start at a low value and not have to care about overflow Tongue

By rolandve

Champion (346)

rolandve's picture

09-02-2023, 12:57

This code is called often, so OldJiffy = Jiffy+10; is a smart optimization. The problem with optimizations though, is that I can think of things, but I am not sure what wil remain after the compiler did its thing. C compilers that are wrappers around the BIOS ( Ascii C and Fusion ) can only optimize so much.

By mpsantos7

Supporter (10)

mpsantos7's picture

12-02-2023, 03:58

Hi there

I wrote the code from Beginning MSX-C:First Volume, page 15.
https://archive.org/details/MSX-CJoukan/page/n13/mode/2up

It is a program to find friend numbers. The result for pair (1184,1210) is what is written in the book: 356 seconds.

The problem, is that Fusion-C (SDCC) and Hitech-C (native) executables give the same result in almost half the time

Ok. It is a limited benchmark, mas there are a lot of integer sums and loops.

Are there any tricks in the MSX-C compiler to be as efficient as the others?

By rolandve

Champion (346)

rolandve's picture

12-02-2023, 08:57

There is the non recursive pragma directive so parameters are passed in registers and not on the stack, but that's about it. Printf is a pig an slow but isn't called that often. You could turn off the screen buffer (setbuf), that keeps the output until the program terminates or after a trigger causes it to flush. For simple uses you could use ldirvm to throw your text (in a char *) on the screen, but that requires more work because you would need another way to generate your output string.

You could alter your .bat (c.bat or msxc.bat) and 'rem' the line that removes the.MAC file. This is the assembly that Ascii C creates. You can compare the output at the lowest level. My advice after banging my head with Ascii C many times: skip it and go for either MSXgl or Fusion. MSXgl skips the BIOS where possible, Fusion uses the BIOS. Skipping the BIOS is faster.

By mpsantos7

Supporter (10)

mpsantos7's picture

14-02-2023, 01:20

Pragmas directives made no difference. I found an optimizer made by Xelasoft but it didn't make any difference either.
Interestingly, I tested other programs with loops and MSX-C did very well. The problem then must be the integer sum routines.

Unfortunately I don't know assembler then all I can do is leave the generated files here for a good soul to look over.

First MSX-C source and the MAC file

#include 
#pragma nonrec
main()
{
  int j, s, sum();
  for ( j = 2; j <=  2000; ++j ) {
   s = sum( j );
   if ( s > j && sum( s ) == j )
    printf( "%d %d\n", j, s );
  }
}

sum( n )
int n;
{
  int i, s;
  s = 0;
  for ( i = n/2; i >= 1; --i )
   if ( (n % i) == 0  ) s += i;
  return  s;
}

;	MSX-C ver 1.20p   (code generator)

	cseg
?59999:
	defb	37,100,32,37,100,10,0

main@:
	ld	de,2
@1:
	ld	hl,2000
	call	?CPSHD
	ret	c
	ld	l,e
	ld	h,d
	push	de
	call	sum@
	ex	de,hl
	pop	hl
	push	hl
	call	?CPSHD
	jp	nc,@0
	push	de
	push	hl
	ex	de,hl
	call	sum@
	pop	bc
	pop	de
	ld	a,l
	cp	c
	jr	nz,$+4
	ld	a,h
	cp	b
	jp	nz,@0
	push	de
	push	bc
	ld	bc,?59999
	push	bc
	ld	hl,3
	call	printf
	pop	bc
	pop	bc
	pop	bc
@0:
	pop	de
	inc	de
	jp	@1

	dseg
?17:	defs	2
?19:	defs	2
	cseg

sum@:
	ld	(?17),hl
	push	hl
	ld	hl,0
	ld	(?19),hl
	pop	hl
	ld	de,2
	call	?DVIHD
@4:
	ld	de,1
	call	?CPSHD
	jp	c,@2
	ld	e,l
	ld	d,h
	push	hl
	ld	hl,(?17)
	call	?DVIHD
	pop	bc
	ld	a,e
	or	d
	jp	nz,@3
	ld	hl,(?19)
	add	hl,bc
	ld	(?19),hl
@3:
	ld	l,c
	ld	h,b
	dec	hl
	jp	@4
@2:
	ld	hl,(?19)
	ret


	public	main@
	public	sum@
	extrn	printf
	extrn	?CPSHD
	extrn	?DVIHD

	end

By mpsantos7

Supporter (10)

mpsantos7's picture

14-02-2023, 01:26

And now the most efficient and horrible code generated by the Hitech compiler, or It was my intetion however code tags didn't work and the forum refuses to accept it.

;NAMIGOS.C: 4: int main() {
psect text
global _main
_main:
global ncsv, cret, indir
call ncsv
defw f45
;NAMIGOS.C: 5: int i, j, sum_j;
;NAMIGOS.C: 6: for (i=1; i <= 10000; i++ ) {
ld (ix+-2),.low.1
ld (ix+1+-2),.high.1
jp l6
l3:
;NAMIGOS.C: 7: int sum_i = 0;
ld (ix+-8),.low.0
ld (ix+1+-8),.high.0
;NAMIGOS.C: 8: for ( j=1; j

By rolandve

Champion (346)

rolandve's picture

16-02-2023, 10:16

Nice, you found that xelasoft tool. I couldn't find it. Have the address?

By rolandve

Champion (346)

rolandve's picture

16-02-2023, 19:55

I am no expert at Z80 assembly, but seeing that his oft uses ix, I think it looks like his oft uses all of the Z80 capabilities where as Ascii C only uses a had full of standard registers.

By rolandve

Champion (346)

rolandve's picture

23-02-2023, 23:09

Issue: I am showing a picture, waiting for a keypress before the next one. However: I am reading the keyboard with NEWKEY in the routine before the picture. These keys presses get buffered so my kbit() routine exits immediately.

I am using NEWKEY to scan for keys like up and down. Each keypress however generates about 35 or 40 hits. Kilbuf() however does not empty that buffer, it's completely ignored, so my routine gets executed way too many times. I have tried to manually set the NEWKEY row to 255, I've tried to use OLDKEY as a way to detect the moment I let go of the key but that doesn't work. Is there a smart way to detect the press of a single key and ignore the other measured moments in between?

By aoineko

Paladin (902)

aoineko's picture

24-02-2023, 00:11

Sadly OLDKEY array is reset at the end of the default BIOS's ISR so program can't use it.
You have to backup previous state of NEWKEY (at least the part you want to handle) to be able to detect the input that occurs during a frame.

Page 65/68
58 | 59 | 60 | 61 | 62 | 63 | 64 | | 66 | 67 | 68