Z80 assembly code for MSX 64K

Door M2X_E1

Rookie (23)

afbeelding van M2X_E1

12-01-2019, 12:49

Hi Guys,
I wonder if anyone can see a problem with the code which prevents it from running correctly on the msx 64K version.
So I've removed the MSX's rom and placed my own one in with code as below.
The VDP is generating the 50hz interrupt signals ok, however for some reason the IORQ is activating about 240 times within each 50hz cycle. I dont expect this to happen as the iorq should only activate to acknowlege the 50hz interrupt at most, also the iorq will activate when writing to the output port, which should be just once per second.

All i can think of is that the program is making an invalid jump somewhere but i cannot find any problem. I've tried this on Zemu and it seems to work ok.
I've included the code below along with a snapshot of the binary.

0000:	(runtime initialising, pre main)
    F3            [ 4]   22 	DI	;disable interrupts (will be re-enabled in main program)
                             23 	;; set paging registers to allow rom at low 32K memory and ram at high 32K
                             24 	;set register 0xA8 to value (10100000) 0xA0	
    0E A8         [ 7]   25 	ld c, #0xA8
    3E A0         [ 7]   26 	ld a, #0xA0
    ED 79         [12]   27     out (c),a
                             29 	;; Stack at the top of memory.
    31 F0 FF      [10]   30     ld  sp,#0xFFF0
                             33 	;; set z80 to receive and process maskable interrupts /INT interrupt mode 1
    ED 56         [ 8]   34 	IM 1
                             36 	;; set vdp to generate 50hz IM1_interrupts
                             38 	;;out 0x99,#32		;;set bit 5
    0E 99         [ 7]   39 	ld c, #0x99
    3E 20         [ 7]   40 	ld a, #32
    ED 79         [12]   41     out (c),a
                             44 	;;out 0x99,#129	;;store in register 1&128 (control reg)
    0E 99         [ 7]   45 	ld c, #0x99
    3E 81         [ 7]   46 	ld a, #129
    ED 79         [12]   47     out (c),a
    CD 00 01      [17]   53     call    _main at 0x0100

                         11     .org    0x38
    F3            [ 4]   12 	DI		;disable further interrupts for now
    CD 13 01      [17]   13     call _IM1_InterruptHandler at location 0x0113
    FB            [ 4]   14 	EI		;re-enable interrupts
    ED 4D         [14]   15 	reti		; return from this handler to where program left off.
0100:	(main program)

                      54 _main::
                             55 ;test.c:7: counter =50;
    FD 21r00r80   [14]   56 	ld	iy, #_counter
    FD 36 00 32   [19]   57 	ld	0 (iy), #0x32
                             58 ;test.c:8: pattern =0;
    FD 21r01r80   [14]   59 	ld	iy, #_pattern
    FD 36 00 00   [19]   60 	ld	0 (iy), #0x00
                             61 ;test.c:11: __endasm;
    FB            [ 4]   62 	EI
                             63 ;test.c:12: while(1==1){}
                         64 00102$:
                             65 ;test.c:14: }//end of main
    18 FE         [12]   66 	jr	00102$

Function IM1_InterruptHandler
                         71 _IM1_InterruptHandler::
                             72 ;test.c:32: counter=counter-1;
    FD 21r00r80   [14]   73 	ld	iy, #_counter
    FD 7E 00      [19]   74 	ld	a, 0 (iy)
    21r00r80      [10]   75 	ld	hl, #_counter
    C6 FF         [ 7]   76 	add	a, #0xff
    77            [ 7]   77 	ld	(hl), a
0120: interrupt handler (continued)
                             78 ;test.c:33: if(counter==0){
    FD 7E 00      [19]   79 	ld	a, 0 (iy)
    B7            [ 4]   80 	or	a, a
    20 19         [12]   81 	jr	NZ,END_OF_THIS
                             82 ;test.c:34: pattern+=1;
    FD 21r01r80   [14]   83 	ld	iy, #_pattern
    FD 34 00      [23]   84 	inc	0 (iy)
    FD 7E 00      [19]   85 	ld	a, 0 (iy)
                             86 ;test.c:35: counter=50;
    FD 21r00r80   [14]   87 	ld	iy, #_counter
    FD 36 00 32   [19]   88 	ld	0 (iy), #0x32
                             89 ;test.c:42: __endasm;
    3Ar01r80      [13]   90 	ld	a,(#_pattern);
    0E 00         [ 7]   91 	ld	c, #0x00
    ED 79         [12]   92 	out	(c),a

                             94 ;test.c:47: __endasm;
    DB 99         [11]   95 	in	a, (#0x99) ;read from status port to clear VDP interrupt
                             96 ;test.c:48: }
    C9            [10]   97 	ret			;return from handler, should goto interrupt vector which called this, then it will end isr and return to main.

binary hex view:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000  F3 0E A8 3E A0 ED 79 31 F0 FF ED 56 0E 99 3E 20  ó.¨> íy1ðÿíV.™> 
00000010  ED 79 0E 99 3E 81 ED 79 CD 00 01 FF FF FF FF FF  íy.™>.íyÍ..ÿÿÿÿÿ
00000020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000030  FF FF FF FF FF FF FF FF F3 CD 13 01 FB ED 4D FF  ÿÿÿÿÿÿÿÿóÍ..ûíMÿ
00000040  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000050  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000060  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000070  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000080  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000090  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000A0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000B0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000C0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000D0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000E0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000F0  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000100  FD 21 00 80 FD 36 00 32 FD 21 01 80 FD 36 00 00  ý!.€ý6.2ý!.€ý6..
00000110  FB 18 FE FD 21 00 80 FD 7E 00 21 00 80 C6 FF 77  û.þý!.€ý~.!.€Æÿw
00000120  FD 7E 00 B7 20 19 FD 21 01 80 FD 34 00 FD 7E 00  ý~.· .ý!.€ý4.ý~.
00000130  FD 21 00 80 FD 36 00 32 3A 01 80 0E 00 ED 79 DB  ý!.€ý6.2:.€..íyÛ
00000140  99 C9

So the program should just count 50 cycles then increment the value being sent to the output port 0 once every second.

Any thoughts?


Aangemeld of registreer om reacties te plaatsen

Van sd_snatcher

Prophet (3458)

afbeelding van sd_snatcher

12-01-2019, 13:25

Here's a tip for you: if you code your program for MSX-DOS, the whole 64KB of RAM will be available without hassle. Smile

Van Manuel

Ascended (18092)

afbeelding van Manuel

12-01-2019, 14:01

Also, which MSX machine are you using exactly and which expansion cartridges have you plugged in? There might be interrupts generated from other hardware.

Van Grauw

Ascended (10022)

afbeelding van Grauw

12-01-2019, 14:02

No need to DI at 38H, the interrupts are automatically disabled by the Z80 on ISR entry.

I can’t really see anything that would be causing this problem just by looking. Although in terms of program design, there are things I would do differently Big smile. Maybe the VDP setup is incomplete. I would recommend to test with a debugger in an emulator.


Enlighted (5847)

afbeelding van NYYRIKKI

12-01-2019, 15:33

Replacing main ROM with something you wrote in C... I have really hard time trying to figure out the thinking process that let you to believe that this was a good idea.

M2X_E1 wrote:

Any thoughts?

- No, it was not a good idea.
- Are you sure your RAM is in slot 2?
- Build your setup in to proper emulator such as openMSX or BlueMSX where you can use debugger to step trough your code instruction by instruction in order to see what goes wrong.
- If your compiler produces this kind of assembly then just throw it away and use something else.

Van M2X_E1

Rookie (23)

afbeelding van M2X_E1

13-01-2019, 13:14

The code which came from the compiler wasn’t that great I agree, it does work and since it was a small test program I decided not leave as it was for now.

I’ve discovered the problem was the command register in the PPI which needed set before i could then allocate the ram to desired slots. seems to be working now.

Thanks you Sd_snatcher, Manuel and Grauw for your help, your positive and constructive info is certainly appreciated.


Van Edevaldo

Master (141)

afbeelding van Edevaldo

14-01-2019, 23:36

It is really common nowadays to see one asking for help in trying something and other people criticizing the attempt/idea.

I don't get it. It is so ridiculous. It is like someone asking for help about how to boot into MSX-DOS and someone answering that using a MSX nowadays is a bad idea.

The thing about MSX is that hardware is so simple and "understandable" compared to anything else you could find nowadays. A microcontroller will easily have 2000 page manual. This makes MSX a great platform to try things and experiment and be creative.

If someone is trying to replace the ROM of an MSX and write a complete new firmware for it using any languange/compiler and you think it is a bad idea it is your limited thinking that is at fault here. It is his MSX, his time, his challenge, his fun, his idea. Judgement is not welcome. He needs technical help and encouragement. Naysayers should limit themselves to help technically.

M2X_E1, I'm glad that you found the problem. I have no idea what you are attempting. I would love to hear about it.


Enlighted (5847)

afbeelding van NYYRIKKI

15-01-2019, 01:44

Ok, ok, I could have asked the reasons in a nice way, but I didn't... Yes, I'm sorry.

Personally I do all kind of stupid stuff all the time, so I'm probably even one of the worst person around here to criticize anyone about that. To be honest I'm really interested to hear some kind of idea or vision about what this is all about. For me this just sounds a bit like trying to go trough a brick wall by using teaspoon while you can easily either walk by or climb over... The thing is that it may be that I just don't have enough imagination or then the whole purpose is just to figure out if it is possible or not... maybe it is even sports like effort to do this all in 1970's tools (and nothing wrong with that either) but the truth is that now we just don't know.

I did select very wrong words to express my self, but let's say that I still think that this still MIGHT be a case where we now just got a wrong question to solve... and with that I mean that the other option is that there might be now some real issue that needs solving, but the approach / question is set "wrong"... I think it is needless to point out that this kind of approach takes the "MSX standard" out of equation, so the end result can not really be called MSX program and the generated software will be locked to this mysterious undefined hardware we've been told nothing about... TBH ATM I even think that all of this IS actually intentional.

Van Edevaldo

Master (141)

afbeelding van Edevaldo

15-01-2019, 02:22


Nothing particular about you. I have noticed a similar pattern in other posts/people and it happens that this point was a tipping point for me. I'm actually sorry it was your message that triggered my reaction, but I had to comment. Your message was not particularly the worse. The last 3 phrases of your post were very good technical advice. You have done great contributions to the MSX in software and comments here over the years. And when you write on a topic I'm researching, I really stop and read it.

But all in all there is nothing 100% rational about using and developing for an MSX in 2019 and it is amazing that after 35+ years there is still people using it and making new stuff for it. And new people coming to this forums (me included).

Many tend to criticize when the idea of another one of a kind sound/video/mass storage extension appears. Maybe from our desire that the same effort was put to enhance the current software/extensions instead of risk becoming another one of a kind thing that dies over time. But, in the end, that is fine also. It may be an entry point for someone to acquire the know how to make another project that will be an even more valuable contribution. When people get stimulated incredible things can happen.


Enlighted (5847)

afbeelding van NYYRIKKI

15-01-2019, 19:17

HI, Edevaldo

I must say that I'm kind of pessimistic person, who rarely believes in miracles... It is always wonderful to dream, but things usually tend to turn wrong way at some point. After saying that I must say that I've witnessed miracles few times right here...

Who would have ever thought that Norakomi can actually make Manbow2? Did anyone expect Prodatron to implement SymbOS on MSX when he came to this forum? Miracles are something individuals do when they get support and this is why I think it is important to answer the questions, no matter if they have been gone through over and over again or if the idea seems bad. TBH I hope that I would have figured out that PPI needs I/O directions defined since that would have made me helpful, but as I'm so biased by the MSX standard that does this for me, I didn't even see the problem.