Well calling the main ROM BIOS can be done directly as noted.
The problem is the SUBROM, that requires a special way due to DOS behavior. If we look at the calling SUBROM routine, notice that it puts the code on the stack, then call it, and removes from it. Then, as the stack goes from higher to lower memory address, it has to push the routine code backwards. As the stack is 16-bit aligned, it adds something like a NOP to fill, not because is required.
Notice that here:
ld hl,0 add hl,sp ; HL = offset of routine ld a,#C3 ld (H_NMI),a ld (H_NMI+1),hl ; JP in NMI hook
What it does is get the routine address (that is at the stack address), and then set a JP (#C3 = JP opcode) on the NMI hook.
The truth is that is a bit weird, pushing the routine into the stack on each call, I think the calling SUBROM would be a good candidate for creating it as routine to put at page 3, as said, at program start. This is, at the very start push the routine and set the NMI hook.
Hi All,
Newbie here!
I learned how to program in a MSX back in the 80s. Today I work as a Java developer (boring I know). Because I also learned a little bit of C, I started writing programs for MSX in that language. Version 1.20 to be precise.
The question:
Is it possible to call a subrom routine from C (I am trying to stay away from Assembly)?
Basically I want to convert the code bellow into C programming.
;--- REDCLK ------------------------------------------------------------------ ;Address : #01F5 ;Function : Read clock-RAM ;Input : C - clock-RAM address ; xxBBAAAA ; ||++++-- address ; ++------ Block-number ;Output : A - Read value in lowest four bits ;Registers: F REDCLK equ 01F5h public RdClck extrn _CALSUB RdClck: ld c,a ld ix,REDCLK jp _CALSUB end
Thanks!
Hi all,
I found the answer to my own question! :-)
MSX-C example to get the system's current data without messing with Assembly:
#include #include #define GETIME 0x2c #define getTime(rTime) rTime.bc = GETIME, callx(5, &rTime) main() { REGS rTime; printf("\xc"); for ( ;!kbhit(); ) { getTime(rTime); printf("\xb %02d:%02d:%02d\n", rTime.hl / 256, (int)rTime.a, rTime.de / 256); } }
Thanks for the insights!
Another variant just for fun:
#include #include #define GETIME 0x2c VOID now(regs) REGS *regs; { regs->bc = GETIME; callx(5, regs); printf("\xb %02d:%02d:%02d\n", regs->hl / 256, (int)regs->a, regs->de / 256); now(regs); } main() { REGS *regs; printf("\xc"); now(regs); }
Hello, guys.
I tried to do some simple things on MSX-C, and all went well except I could not like the make script I did myself reading https://medium.com/relearning-msx/relearning-msx-13-ecb02de3... and other stuff.
https://github.com/brawaga/msx-dos-utils/blob/master/make.bat
What I dislike here, I had to have source file on separate drive B:, when having MSX-C on A:, and please note change directory commands for each utility call.
But all went well for less.com, so it did not actually bother me, until I started to do something more complicated.
Well, I have, say, mem.h and mem.c and building mem.c with make.bat b:mem.
CF says it does not see mem.h, included in mem.c. When I remove CDs from the batch, it does see mem.h, but cannot see stdio.h anymore.
Is there a way to pass CF and CG directories to look files up? I guess this will be a solution for my problem, and I will not be obliged to use separate drives anymore.
If there is other solution to builld such things, I will appreciate either.
Finally, I discovered I must set up INCLUDE environment variable, but no hint how to put multiple directories here, I tried comma and semicolon as separator with no effect. Anybody knows how to include multiple directories? Maybe some command line arguments supported also for CF.COM and CG.COM?
Whoever runs into same problem, there's the solution from me: https://github.com/brawaga/msx-dos-utils/tree/master/workon.
Hi All,
I am trying to use a pointer to to read MSX system variables. It however doesn't work like I hoped. In all variants the switch results in all MSX types. My question is: how can I use a pointer to read and use system variables? The part of my failed code is below. Thanks!
int *msx; msx= 0x2D; // also tried (int *)0x2D // (*(int *)0x2D) switch ( *msx ) { case 0: puts("MSX 1\n"); case 1: puts("MSX 2\n"); case 2: puts("MSX 2+\n"); case 3: puts("Turbo-R\n"); }
You are missing a break after each puts statement. Without that the code will just fall through.
So change it to something like:
case 0: puts("MSX 1\n"); break; case 1:
Even with the break, the MSX Turbo R of OpenMSX reports as MSX1 so that didn't work.
Note that when you run this from a dos prompt it will always return 0 from address 0x2D. You are just reading a value from RAM, see Chapter 2.3.
You need to have the BIOS rom active at page 0 to be able to read out the MSX type (or do an inter-slot call using for example RDSLT):
uint8_t msx; void main() { __asm ld hl,#0x2D // Address ld a,#00 // Slot ID call 0x0C // RDSLT ld (_msx),a __endasm; printf("%i", msx); }