-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Porting kegs-universal changes to gsplus. #31
Conversation
@@ -0,0 +1,179 @@ | |||
# kegs-universal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is merely a copy of the kegs-universal README file.
@@ -0,0 +1,9 @@ | |||
;;; Directory Local Variables |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lets emacs uses tabs in the same way as the rest of the kegs codebase.
@@ -1257,7 +1258,10 @@ update_mouse(int x, int y, int button_states, int buttons_valid) | |||
if( (g_mouse_ctl_addr == g_mouse_dev_addr) && | |||
((g_adb_mode & 0x2) == 0)) { | |||
g_adb_mouse_valid_data = 1; | |||
adb_add_mouse_int(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes the mouse interrupt behavior when using an Apple2c rom. (see comment in code)
@@ -1267,6 +1271,13 @@ update_mouse(int x, int y, int button_states, int buttons_valid) | |||
int | |||
mouse_read_c024(double dcycs) | |||
{ | |||
return mouse_read_c024_clamp(dcycs, 0x3f); | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The apple2c mouse i/o ports in moremem.c call this function with clamp=2 in order to obtain detailed mouse position updates instead of aggregated updates in range -0x3f,+0x3f like a 2gs.
@@ -58,6 +58,7 @@ extern byte *g_rom_fc_ff_ptr; | |||
extern byte *g_rom_cards_ptr; | |||
extern double g_cur_dcycs; | |||
extern int g_rom_version; | |||
extern int g_a2rom_version; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The detected apple 2 rom version. Values are '2', 'e', 'c', 'C', and 'g' for the apple2/2+, apple2e, apple2c, apple2c+, and apple2gs respectively.
src/config.c
Outdated
char *g_cfg_file_def_name = "Undefined"; | ||
char **g_cfg_file_strptr = 0; | ||
int g_cfg_file_min_size = 1024; | ||
int g_cfg_file_min_size = 256; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows the file selection dialog to select files that are only 256 bytes long. Usefull for the c600 rom.
src/config.c
Outdated
@@ -228,6 +230,7 @@ Cfg_menu g_cfg_joystick_menu[] = { | |||
Cfg_menu g_cfg_rom_menu[] = { | |||
{ "ROM File Selection", g_cfg_rom_menu, 0, 0, CFGTYPE_MENU }, | |||
{ "ROM File", KNMP(g_cfg_rom_path), CFGTYPE_FILE }, | |||
{ "C600 ROM File", KNMP(g_cfg_c6rom_path), CFGTYPE_FILE }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New rom selection entry to provide a c600 rom. This is critical for the 2, 2+, 2e models because the main rom does not contain the disk 2 boot rom.
} else { | ||
fatal_printf("The ROM size should be 128K or 256K, this file " | ||
"is %d bytes\n", len); | ||
} else if(len == 12*1024) { /* ][ and II+ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What follows loads 12KB, 16KB, and 32KB rom files.
@@ -879,22 +906,57 @@ config_load_roms() | |||
} | |||
fclose(file); | |||
|
|||
memset(&g_rom_cards_ptr[0], 0, 256*16); | |||
/* Detect A2 roms */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this detects what kind of rom has been loaded using the official method.
/* Slot roms */ | ||
memset(&g_rom_cards_ptr[0], 0, 256*16); | ||
/* Initialize c600 rom to be diffs from the real ROM, to build-in */ | ||
/* Apple II compatibility without distributing ROMs */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These diffs only apply to the 2gs roms. Other model (except the 2c) need a c600 rom file.
|
||
/* Initialize c700 rom for smartport */ | ||
switch(g_a2rom_version) { | ||
case 'g': case '2': case 'e': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The slot 7 smartport slot rom has been reduced to its simplest expression. All bytes are zero except those that tell the firmware or the operating system that there is a smartport compatible device in slot 7.
@@ -915,6 +977,7 @@ config_load_roms() | |||
|
|||
len = 256; | |||
ret = fread(&g_rom_cards_ptr[i*0x100], 1, len, file); | |||
fclose(file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was a bug in the existing gsplus code. The file would not have been closed if the read had failed (see continue below).
@@ -1592,7 +1654,12 @@ insert_disk(int slot, int drive, const char *name, int ejected, int force_size, | |||
} | |||
} | |||
} | |||
|
|||
if (! dsk->smartport && ! dsk->disk_525) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting a 3.5 inch floppy on an apple 2c+ gives a 1:4 interleaved disk instead of a 1:2 interleaved disk. They did that to accommodate the slower processor (all disk i/o is performed at 1Mhz on the 2c+). Disk images with suffix .po4
loaded a 3.5 inch drive are assumed to have 1:4 interleave.
@@ -637,9 +637,12 @@ defs_instr_start_16 .word 0 | |||
# define GET_ABS_X_RD_WR() \ | |||
GET_2BYTE_ARG; \ | |||
INC_KPC_3; \ | |||
CYCLES_PLUS_2; \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out that some code relies on the fact that instruction INC abs,X
performs a phantom read before reading the actual data. This is often used to double read the language card write enable i/o port. I have implemented this in the C emulation but not the PowerPC assembly version (no way to test).
@@ -507,14 +507,15 @@ iwm_touch_switches(int loc, double dcycs) | |||
break; | |||
case 0xa: | |||
case 0xb: | |||
iwm.drive_select = on; | |||
iwm.drive_select = mig_changedrive(on); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used to map the Apple2c+ 3.5 drives to the 2gs drives (see long comment in moremem.c
)
break; | ||
case 0xc: | ||
case 0xd: | ||
iwm.q6 = on; | ||
break; | ||
case 0xe: | ||
case 0xf: | ||
mig_checkwhead(dsk, on); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this is useful because the 2c+ formatting firmware does not switch heads using the official method but using an undocumented method.
@@ -2007,7 +2008,7 @@ iwm_nibblize_track_35(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) | |||
} | |||
|
|||
phys_sec = 0; | |||
interleave = 2; | |||
interleave = (dsk->image_type == DSK_TYPE_35_4) ? 4 : 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implements 1:4 interleaving for disk images of this new type. Only 3.5 inch floppy images are concerned.
@@ -30,6 +30,9 @@ | |||
#define DSK_TYPE_PRODOS 0 | |||
#define DSK_TYPE_DOS33 1 | |||
#define DSK_TYPE_NIB 2 | |||
#define DSK_TYPE_35_4 4 /* 3.5 disk with 1:4 interleave */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new type of disk image, for 1:4 interleaved 3.5 floppy disks.
@@ -756,11 +758,31 @@ do_reset() | |||
extern int g_scan_int_events ; | |||
extern int g_c023_val; | |||
|
|||
g_c068_statereg = 0x08 + 0x04 + 0x01; /* rdrom, lcbank2, intcx */ | |||
g_c035_shadow_reg = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reset does not initialize the hardware in the same way. The 2 and 2+ do not reset the language card at all. The 2,2+ and 2e have all slots enabled. The 2c has none. All must slow down to 1Mhz when the disk motor is on.
@@ -1704,7 +1726,8 @@ run_prog() | |||
setup_zip_speeds(); | |||
} | |||
|
|||
iwm_1 = motor_on && !apple35_sel && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 2gs firmware for 3.5 inch floppy drives runs at 2.8Mhz. All others run this at 1Mhz.
@@ -1922,11 +1945,7 @@ take_irq(int is_it_brk) | |||
/* Clear B bit in psr on stack */ | |||
engine.stack = ((engine.stack -1) & 0xff) + 0x100; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remaining code deals with an oddity of the 2gs. On the 2gs, a special circuitry forces the processor to read the interrupt vectors in bank $ff (instead of bank $00 if the processor was left to itself). We must do this only for the 2gs because the other models also have interrupt vectors in the language card...
engine.kpc = 0xc764; | ||
} else { | ||
engine.kpc = 0xc765; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of relying on a known RTS in the rom image, the prodos handler for the slot 7 smartport returns by reading the return address from the stack (just like the smartport mli handler in fact.) This was necessary to run the hard disk on an apple2e for instance.
@@ -413,6 +664,8 @@ fixup_intcx() | |||
rom_inc = SET_BANK_IO; | |||
if(((g_c02d_int_crom & mask) == 0) || INTCX) { | |||
rom_inc = rom10000 + (j << 8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following change (and similar changes below) implement the ROMBANK bit in the state register.
@@ -427,6 +680,12 @@ fixup_intcx() | |||
if(((g_c02d_int_crom & (1 << 3)) == 0) || INTCX) | |||
{ | |||
rom_inc = rom10000 + (j << 8); | |||
if(g_c068_statereg & 0x02) { | |||
if((g_a2rom_version == 'C') && (j >= 0xce)) | |||
rom_inc = SET_BANK_IO; /* mig */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MIG chip on the apple2c is mapped at addresses CE00-CFFF of the alternate rom bank.
} | ||
fixup_brks(); | ||
if ((g_c02d_int_crom & 0x80) && !INTCX) { | ||
SET_PAGE_INFO_RD(0xc7, SET_BANK_IO); /* smartport */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The slot7 smart port is now implemented as a slot rom. Therefore it can be enabled or disabled by enabling or disabling the slot7 card. And it can also work on the apple2+ or apple2e.
} | ||
} | ||
fixup_brks(); | ||
fixup_mig(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is because the apple 2c+ mig chip is reset whenever one returns to the main rom bank.
@@ -571,6 +833,8 @@ fixup_altzp() | |||
} | |||
if(rdrom) { | |||
mem0rd = &(g_rom_fc_ff_ptr[0x3d000]); | |||
if((g_c068_statereg & 0x02) && A2CROM) | |||
mem0rd -= 0x10000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternate rom bank again
@@ -835,11 +1105,17 @@ set_statereg(double dcycs, int val) | |||
|
|||
if(_xor & 0x02) { | |||
/* ROMBANK */ | |||
halt_printf("Just set rombank = %d\n", ROMB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement the ROMBANK bit of the state register
return(adb_read_c000()); | ||
|
||
case 0x0c: case 0x0d: case 0x0e: case 0x0f: { | ||
int c = adb_read_c000(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The apple2 keyboard has only uppercase letters
@@ -1246,15 +1529,27 @@ io_read(word32 loc, double *cyc_ptr) | |||
case 0x14: /* c014=rdramwrt */ | |||
return IOR(RAMWRT); | |||
case 0x15: /* c015 = INTCX */ | |||
return IOR(INTCX); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 2c and 2c+ iou chip is in fact different from the 2e or mega2 versions. All these differences are enabled by macro A2CROM
which tests whether g_a2rom_version
is 'c'
or 'C'
. The are much more differences than I expected.
@@ -1289,18 +1584,15 @@ io_read(word32 loc, double *cyc_ptr) | |||
case 0x27: /* 0xc027 */ | |||
return adb_read_c027(); | |||
case 0x28: /* 0xc028 */ | |||
UNIMPL_READ; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c028 switches the alternate rom bank.
case 0x4c: /* 0xc04c */ | ||
case 0x4d: /* 0xc04d */ | ||
case 0x4e: /* 0xc04e */ | ||
g_a2c_mouse &= 0xf3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear 2c mouse data. Note that g_a2c_mouse
can only be non zero when A2CROM is true.
g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); | ||
change_display_mode(dcycs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When setting double hires, only change the display mode when the bit is actually changed.
/* 0xc080 - 0xc08f */ | ||
case 0x80: case 0x81: case 0x82: case 0x83: | ||
case 0x84: case 0x85: case 0x86: case 0x87: | ||
case 0x88: case 0x89: case 0x8a: case 0x8b: | ||
case 0x8c: case 0x8d: case 0x8e: case 0x8f: | ||
/* After checkingthe Language Card schematics */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kegs language card emulation was imperfect. I checked the language card schematics to get it exactly right (and in particular get the double-read aspect correct). And I fixed the emulator to implement the phantom read that some code uses to double-read the language card toggle...
@@ -1656,7 +1999,20 @@ io_read(word32 loc, double *cyc_ptr) | |||
#endif | |||
|
|||
/* 0xc0c0 - 0xc0cf */ | |||
case 0xc0: case 0xc1: case 0xc2: case 0xc3: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some apple2c roms hang when the ram extension card (the "slinky" card) is not emulated. They only work in the real machine because the floating bus eventually returns what the firmware expects.
@@ -1668,10 +2024,13 @@ io_read(word32 loc, double *cyc_ptr) | |||
case 0xdc: case 0xdd: case 0xde: case 0xdf: | |||
return 0; | |||
/* 0xc0e0 - 0xc0ef */ | |||
case 0xe8: case 0xe9: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intercept the drive motor change to correctly remap the a2c+ 3.5 drives to the kegs ones.
@@ -1694,19 +2053,17 @@ io_read(word32 loc, double *cyc_ptr) | |||
} | |||
return float_bus(dcycs); | |||
case 7: | |||
/* c700 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this is now useless because we implement the slot 7 smartport as a slot card.
@@ -1881,6 +2238,9 @@ io_write(word32 loc, int val, double *cyc_ptr) | |||
case 0x27: /* 0xc027 */ | |||
adb_write_c027(val); | |||
return; | |||
case 0x28: /* 0xc028 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Writing to c028 is the official way to swap the rom bank on a 2c. Reading works too.
@@ -2036,6 +2395,8 @@ io_write(word32 loc, int val, double *cyc_ptr) | |||
return; | |||
|
|||
/* 0xc040 - 0xc04f */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reordered the c04x writes in a manner that makes a bit more sense.
if(g_zipgs_unlock < 4) { | ||
if(g_zipgs_unlock >= 4) { | ||
/* nothing */ | ||
} else if(g_a2c_ioudis) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
g_a2c_ioudis can only be false when using an apple2c/2c+ rom.
g_c05x_annuncs |= 1; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear mouse interrupt (only the 2c/2c+ gets there because g_a2c_ioudis is always 1 with other roms.
@@ -2400,7 +2770,24 @@ io_write(word32 loc, int val, double *cyc_ptr) | |||
#endif | |||
|
|||
/* 0xc0c0 - 0xc0cf */ | |||
case 0xc0: case 0xc1: case 0xc2: case 0xc3: | |||
case 0xc0: case 0xc1: case 0xc2: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2c ram extension emulation (slinky)
@@ -2414,9 +2801,12 @@ io_write(word32 loc, int val, double *cyc_ptr) | |||
UNIMPL_WRITE; | |||
|
|||
/* 0xc0e0 - 0xc0ef */ | |||
case 0xe8: case 0xe9: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
intercept drive motor switch to correctly map 2c+ drives to kegs drives
case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: | ||
case 9: case 0xa: case 0xb: case 0xd: | ||
UNIMPL_WRITE; | ||
case 0x8: case 0xc: case 0xe: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MIG responds to writes to c8XX ccXX and ceXX in the alternate rom bank
I'd like to personally "thumbs up" these patches. While the resulting emulations are not quite true-to-form, resulting in a "super" version of the emulated systems, I have been exercising kegs-universal for some time now and the patches are solid. To date, these patches contain the only working emulation of the Apple IIc Plus MIG chip, when combined with the KEGS IWM/3.5 drive emulation, allow KEGS to fully emulate the Apple IIc Plus. MG |
@@ -786,6 +787,12 @@ do_c700(word32 ret) | |||
|
|||
if(ret != 0) { | |||
printf("Failure reading boot disk in s7d1!\n"); | |||
engine.kpc = 0xff59; /* Jump to monitor, fix $36-$39 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is no boot sector, continue scanning the remaining slots. This is done in the "standard way", that is by testing whether 00,01 contain the jump vector used by the powerup monitor code. Otherwise jump into monitor mode (the old A2 reset vector.)
Can not merge. Source is divergent with many conflicts at this point. My fault. Sorry. |
Yep. At this point, this is cooked... |
Only just made aware of this. Fantastic work, and a great pity it wasn't integrated. |
I could port the changes again. This is a lot of manual work. I wouldn't want to do it just to see the request linger until they un-mergeable again. Note that https://github.com/leonbottou/kegs-universal works fine but lacks many of the gsplus features. |
This is the gsplus version of the kegs-universal changes. These changes allow kegs (and now gsplus) to operate using all classic apple 2 roms. See https://github.com/leonbottou/kegs-universal. The supported roms include:
The idea is to add just what's necessary to operate these older roms. The emulated machine essentially remains a 2gs, but with the minimal changes necessary to operate the selected rom. Most of the changes are in file
moremem.c
to support the necessary io-space features of each of these computers. Smaller related changes have been made toadb.c
,config.c
,defs_instr.c
,iwm.c
,sim68516.c
, andsmartport.c
. (see https://github.com/leonbottou/kegs-universal/blob/master/README.md for details). Some of these changes actually improve the 2gs emulation (e.g. the language card double reads, the phantom read with instructionINC abs,X
, the slot powerup scan,...Despite all these changes, the diff remains readable and explainable. I am intending to add comments to all these diffs to explain what they do and make the review easier.