1 /* rrgb, a rough and ready game boy emulator
2 * Copyright (C) 1994 Ian Collier. rrgb changes (c) 1998 Michael Hope
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #if !defined(__sun__) && !defined(__APPLE__)
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #include <netinet/in.h>
40 unsigned char *segments
[NUM_SEGS
];
42 unsigned char mem
[65536];
43 unsigned long tstates
=0;
44 char bank_file_name
[50];
49 int loadImage(char *imageName
, int flags
);
51 /** Names for the system traps. Set A to one of these and call RST 08
52 with parameteres in HL. Any return value will also be in HL.
55 /** Exit the emulator (normal exit). */
57 /** Print the character in L to the screen. */
59 /** Returns the run time in 1/100s. */
63 RST_08_PROFILE_ENTER_LEAF
68 CPU_CLOCKS_PER_SECOND
= 100
73 printf("rrgb: Rough 'n Ready processor only Gameboy emulator.\n"
74 "\tM.Hope " __DATE__
"\n"
76 "\trrgb [-i] [-t] [-p] [-m] [-d] [-s name.bin] image.gb\n"
77 "\t\t-p - Profile code.\n"
78 "\t\t-m - Load map file.\n"
79 "\t\t-d - Enter debugger before running.\n"
80 "\t\t-s - Use name.bin as a segment file.\n"
81 "\t\t-t - Open port 6808 for input.\n"
82 "\t\t-i - Enable 100Hz timer interrupts.\n"
83 "\t\t-k - Run for at most 20s.\n"
92 void handleRST08(struct sregs
*pregs
)
101 if (*pregs
->l
== '\n' || *pregs
->l
== '\r') {
105 case RST_08_GET_CLOCK
: {
106 unsigned ticks
= tstates
/ (CPU_SPEED
/CPU_CLOCKS_PER_SECOND
);
107 *pregs
->e
= (unsigned char)ticks
;
108 *pregs
->d
= (unsigned char)(ticks
>> 8);
111 case RST_08_PROFILE_ENTER
:
112 case RST_08_PROFILE_EXIT
:
113 case RST_08_PROFILE_ENTER_LEAF
:
116 printf("Unsupported RST 08 code %02Xh\n", *pregs
->a
);
120 int main(int argc
,char **argv
)
123 struct sockaddr_in sock
;
129 while ((c
=getopt(argc
, argv
, "kpms:dti"))!=-1) {
140 strcpy(bank_file_name
, optarg
);
168 for (i
=0; i
< NUM_SEGS
; i
++) {
169 segments
[i
] = &mem
[i
*SEG_SIZE
];
173 loadImage(argv
[optind
], flags
);
176 printf("%s:Error: No image file specified.\n",argv
[0]);
179 if (flags
&DSOCKETS
) {
180 /* Open up the socket connection before proceeding */
181 printf("Opening socket 6808...");
184 hsocket
= socket_init(6808);
191 printf("Waiting for connection...");
194 sock_len
=sizeof(struct sockaddr_in
);
195 tsocket
= accept( hsocket
, (struct sockaddr
*)&sock
, &sock_len
);
210 if (flags
&DSOCKETS
) {
214 printf("\nrrgb: Total tstates: %lu.\n", tstates
);
220 int loadImage(char *imageName
, int flags
)
226 if((in
=fopen(imageName
,"rb"))!=NULL
) {
227 size_t got
= fread( mem
, 1, 32768, in
);
229 perror("Error while reading the rom image");
235 /* Try to find the map file */
237 sorted_globals
= NULL
;
239 if ((dot
=strrchr( imageName
, '.'))!=NULL
) {
241 strcpy( map_name
, imageName
);
242 strcat( map_name
, ".map");
243 if (!parse_map( map_name
, &areas
)) {
244 sort_globals( &sorted_globals
, areas
);
248 if (sorted_globals
==NULL
) {
249 printf("Warning: no map file loaded.\n");
255 printf("Couldn't load image %s.\n", imageName
);
260 /* Print out the floating point number stored in HLDE */
261 /* Format: H = Sign|Exponent, LDE = Mantissa */
263 void printGBfloat(unsigned fhl
, unsigned fde
)
268 a
= (65536.0 * (double)(fhl
&0x0ff))+(double)fde
;
270 /* Multiply by 2^exponent */
271 /* Seems to be normalised or something */
272 a
*=pow(2.0,(double)((fhl
>>8)&~0x080)-88.0);
280 /* Switch in bank /bank to segment /segment */
281 void switchBank( int segment
, unsigned bank
)
290 binFP
= fopen( bank_file_name
, "r+b" );
292 /* Commit the last block first */
293 if (fseek( binFP
, last_bank
*SEG_SIZE
, SEEK_SET
)==0) {
294 if (fwrite(segments
[segment
], 1, SEG_SIZE
, binFP
)<SEG_SIZE
) {
295 printf("\nrrgb: Failed write of bank %u.\n", last_bank
);
298 printf("\nrrgb: commited block %u.\n", last_bank
);
303 printf("\nrrgb: Failed write of bank %u.\n", last_bank
);
308 binFP
= fopen( bank_file_name
, "rb" );
310 if (fseek( binFP
, bank
*SEG_SIZE
, SEEK_SET
)==0) {
311 if (fread( segments
[segment
], 1, SEG_SIZE
, binFP
)<SEG_SIZE
) {
312 printf("\nrrgb: Incomplete read in bank %u.\n", bank
);
316 /* printf("%02X %02X %02X %02X\n", segments[segment][0], segments[segment][1], segments[segment][2], segments[segment][3] );*/
319 printf("\nrrgb: Unable to seek to bank %u.\n", bank
);
324 printf("\nrrgb: Warning: No block file open.\n");
327 /* Handle a RST 38 (system call) */
328 int handle_sys(int scall
, int parameter
)
333 /* Read in from telnet */
334 if (flags
&DSOCKETS
) {
335 return socket_get(tsocket
);
341 /* Write to telnet */
342 if (flags
&DSOCKETS
) {
343 buffer
[0]=(parameter
&0x0ff);
344 return socket_write( tsocket
, buffer
, 1);
349 /* Return !0 if data is available */
350 if (flags
&DSOCKETS
) {
351 return socket_poll( tsocket
);