How to call from a specified address
Write the address at which the non-resident program will be executed in advance, and after loading the non-resident program, execute it from this address.
< Program description example>
fid = GFS_NameToId((Sint8 *)fname); /* fname is a non-resident program */ GFS_Load(fid, 0, 0x6080000, GFS_BUFSIZ_INF); /* Get the start address from the map file of the non-resident program */ ((volatile void (*)())(0x6081000))();
<Declaration when linking a program>
GCC -m2 -Xlinker -Tkernal.cof -Xlinker -e -Xlinker ___Start ....
In this example, if the address of the nonresident program's execution start function changes, the program must be recompiled.
Define a function using an external declaration, and set the address for the externally declared function using the -defsym option when linking. The function is executed after loading the non-resident program.
< Program description example>
extern void SUB_main1( void ); #define SUB_ADDR 0x06080000 void main( void ) { : /* Example of loading a non-resident program */ buf[0].type = CDBUF_COPY; buf[0].trans.copy.addr = (Uint32)SUB_ADDR; : slCdLoadFile(); /* Execute non-resident program */ SUB_main1(); : }
<Declaration when linking a program>
GCC -m2 -Xlinker -defsym -Xlinker _SUB_main1=0x06081000 ¥ -Xlinker -Tkernal.cof -Xlinker -e -Xlinker ___Start ....
The address of the execution start function of the non-resident part will be undefined, so set the address temporarily, create the non-resident program, then obtain the real execution start address from the map file of the non-resident part and set the address again. You may need to fix it and link it.
When programming, be careful not to create a function with the same name as the resident part in the object file. (For example, the main function may conflict.)
Set the start address of the non-resident part to the same address as the reading start address of the resident part.
When creating the non-resident part, specify the linker's -R option and specify the executable file for the resident part (for example, Kernal.COF).
GCC -m2 -Xlinker -R -Xlinker kernal.cof .....
With this specification, symbols from the resident part are extracted and included in the non-resident program.
If the same function exists even if the library to be used is linked in the same way as the resident part, the information in the COFF file specified with -R will take precedence.
if ( CDC_GetHirqReq() & CDC_HIRQ_DCHG ) { SYS_EXECDMP(); /* Call multiplayer */ }
There is no problem with this process,
only. Operation cannot be guaranteed if the tray open check is performed using any other method.
/* Get the first frame address of the CDDA track specified by trackno */ Sint32 GetCDStartFrame(Uint8 trackno) { CdcPos Pos; CdcStat stat; CDC_POS_PTYPE(&pos) = CDC_PTYPE_TNO; CDC_POS_TNO(&pos) = trackno; CDC_POS_IDX(&pos) = 1; CDC_CdSeek(&pos); while(1) { CDC_GetCurstat(&stat); if ( CDC_STAT_STATUS(&stat) == CDC_ST_PAUSE ) { break; } } return CDC_STAT_FAD(&stat); }
Another method is to refer to the TOC (Table Of Contents) of the disk and refer to the obtained table.
This table stores 4 bytes for each track from track 1 to the lead-out start frame address.
Regarding the function CDC_TgetToc, which obtains the TOC,
"PROGRAMMER'S GUIDE CD Communication Interface User's Manual (CD Part)"
8.2 Function details No. 1.5
For information on the acquired TOC
"PROGRAMMER'S GUIDE CD Communication Interface User's Manual (CD Part)"
7.2 Data Details 7.2.3 TOC Information/Session Information No 3.0
There is a description in.
If you are using the GFS library, repeating GFS_Load() will accomplish your goal if the file is already open.
Normally, it is a good idea to perform retry processing several times. Avoid running the retry process in an infinite loop, and move the process to the multiplayer without displaying an error message.
This is done by specifying the resident mode with the GFS_SetGmode function of the GFS library, reading the file once from the CD-ROM and making it resident, and then calling the GFS functions GFS_Seek, GFS_Fread, etc. in the same way as from the CD-ROM. It allows you to read from the CD buffer without accessing the CD-ROM again.
In the GFS library, the default value of the mode specified by the GFS_SetGmode function above is destroyed (GFS_GMODE_ERASE), and by making it resident (GFS_GMODE_RESIDENT), for example, after reading data from a CD-ROM in resident mode, CDDA playback is possible. Let it run.
During execution, you can use GFS functions to read data from the CD buffer and use it like a data buffer.
Please note that if you move (seek) or read (read) more than 200 sectors, the CD-ROM will be accessed, so please do so within the maximum 200 sectors.
Also, if you do not use this method, be sure to use the GFS_SetGmode function to return to discard mode.
< example> CD
A sample program that makes data resident in a buffer and reads it during CDDA playback (However, since this program is only for explaining the flow, no error checking is performed. Be sure to add it when installing.)
/* Set resident mode */ GFS_SetGmode(gfs, GFS_GMODE_RESIDENT); /* Read file into CD buffer */ fid = GFS_NameToId( "sample.dat"); if ( fid> = 0 ) { GFS_Open( fid); GFS_NwCdRead( gfs, 200 ); } /* Play CDDA */ CDC_PLY_STYPE(&ply) = CDC_PTYPE_TNO; CDC_PLY_STNO(&ply) = 2; CDC_PLY_SIDX(&ply) = 0; CDC_PLY_ETYPE(&ply) = CDC_PTYPE_TNO; CDC_PLY_ETNO(&ply) = 3; CDC_PLY_EIDX(&ply) = 0; CDC_PLY_PMODE(&ply) = CDC_PM_DFL; ret = CDC_CdPlay(&ply); /* CDDA Read from CD buffer during playback */ GFS_Seek( gfs, GFS_SEEK_SET ); GFS_Fread( gfs, 10, buf, 10*2048 );
Use CDC I/F library.
Since CD-ROM access occurs midway through, set the CD-DA playback range and repeat count again.
To resume playback after seeking to the original position, set "Do not change pickup position".
Also, immediately before executing drive commands such as play and seek, the tray should be opened/closed (DCHG flag) and< FATAL> You should check the condition.
< example>
A simple sample program showing how to play CDDA and obtain pose positions.
/* Initialization */ Sint32 ret; Sint32 fad; CdcStat stat; CdcPly ply; CdcPos pos; // Play track numbers 5-17 infinite times CDC_PLY_STYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_STNO (&ply)=5; CDC_PLY_SIDX (&ply)=0; CDC_PLY_ETYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_ETNO (&ply)=17; CDC_PLY_EIDX (&ply)=0; CDC_PLY_PMODE(&ply)=0x0F; // Start playing CDC_CdPlay(&ply); while (1) { /* Main loop */ : : /* CD access occurs using GFS or SGL */ if (access==TRUE){ CDC_POS_TYPE(&pos)=CDC_PTYPE_NOCHG; /* CD-CA PAUSE */ CDC_CdSeek(&pos); /* PAUSE execution */ /* Get the FAD of the pose position (with a few frames of error) */ ret = CDC_GetCurStat(&stat); if (ret != CDC_ERR_OK) { return NG; } fad = CDC_STAT_FAD(&stat); : /* Perform CD access using GFS or SGL */ : /* CD-DA playback restart processing */ CDC_POS_TYPE(&pos)=CDC_PTYPE_FAD; /* Specify restart position */ -> CDC_POS_FAD (&pos)=fad; /* Specified by FAD */ CDC_CdSeek(&pos); /* Execute seek */ /* Setting CD playback parameters */ /* ・5 to 17 tracks */ /* ・Repeat infinite times */ /* ・Do not change the pickup position */ CDC_PLY_STYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_STNO (&ply)=5; CDC_PLY_SIDX (&ply)=0; CDC_PLY_ETYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_ETNO (&ply)=17; CDC_PLY_EIDX (&ply)=0; CDC_PLY_PMODE(&ply)=(CDC_PM_PIC_NOCHG | 0x0F); CDC_CdPlay(&ply); /* Resume execution */ } : : : slSynch(); /* etc. */ }