/************************************************************************/ /* KEGS: Apple //gs Emulator */ /* Copyright 2002 by Kent Dickey */ /* */ /* This code is covered by the GNU GPL */ /* */ /* The KEGS web page is kegs.sourceforge.net */ /* You may contact the author at: kadickey@alumni.princeton.edu */ /************************************************************************/ const char rcsid_moremem_c[] = "@(#)$KmKId: moremem.c,v 1.251 2004-11-19 01:55:50-05 kentd Exp $"; #include "defc.h" extern char g_kegs_version_str[]; extern byte *g_memory_ptr; extern byte *g_dummy_memory1_ptr; extern byte *g_slow_memory_ptr; extern byte *g_rom_fc_ff_ptr; extern byte *g_rom_cards_ptr; extern word32 slow_mem_changed[]; extern int g_num_breakpoints; extern word32 g_breakpts[]; extern Page_info page_info_rd_wr[]; extern int Verbose; extern int g_rom_version; extern int g_user_page2_shadow; /* from iwm.c */ int g_num_shadow_all_banks = 0; #define IOR(val) ( (val) ? 0x80 : 0x00 ) extern int g_cur_a2_stat; int g_em_emubyte_cnt = 0; int g_paddle_buttons = 0; int g_irq_pending = 0; int g_c023_val = 0; int g_c029_val_some = 0x41; int g_c02b_val = 0x08; int g_c02d_int_crom = 0; int g_c031_disk35 = 0; int g_c033_data = 0; int g_c034_val = 0; int g_c035_shadow_reg = 0x08; int g_c036_val_speed = 0x80; int g_c03ef_doc_ptr = 0; int g_c041_val = 0; /* C041_EN_25SEC_INTS, C041_EN_MOVE_INTS */ int g_c046_val = 0; int g_c05x_annuncs = 0; int g_c068_statereg = 0; int g_c08x_wrdefram = 0; int g_zipgs_unlock = 0; int g_zipgs_reg_c059 = 0x5f; // 7=LC cache dis, 6==5ms paddle del en, 5==5ms ext del en, // 4==5ms c02e enab, 3==CPS follow enab, 2-0: 111 int g_zipgs_reg_c05a = 0x0f; // 7:4 = current ZIP speed, 0=100%, 1=93.75%, F=6.25% // 3:0: always 1111 int g_zipgs_reg_c05b = 0x40; // 7==1ms clock, 6==cshupd: tag data at c05f updated // 5==LC cache disable, 4==bd is disabled, 3==delay in effect, // 2==rombank, 1-0==ram size (00:8K, 01=16K, 10=32K, 11=64K) int g_zipgs_reg_c05c = 0x00; // 7:1==slot delay enable (for 52-54ms), 0==speaker 5ms delay #define EMUSTATE(a) { #a, &a } Emustate_intlist g_emustate_intlist[] = { EMUSTATE(g_cur_a2_stat), EMUSTATE(g_paddle_buttons), EMUSTATE(g_em_emubyte_cnt), EMUSTATE(g_irq_pending), EMUSTATE(g_c023_val), EMUSTATE(g_c029_val_some), EMUSTATE(g_c02b_val), EMUSTATE(g_c02d_int_crom), EMUSTATE(g_c031_disk35), EMUSTATE(g_c033_data), EMUSTATE(g_c034_val), EMUSTATE(g_c035_shadow_reg), EMUSTATE(g_c036_val_speed), EMUSTATE(g_c03ef_doc_ptr), EMUSTATE(g_c041_val), EMUSTATE(g_c046_val), EMUSTATE(g_c05x_annuncs), EMUSTATE(g_c068_statereg), EMUSTATE(g_c08x_wrdefram), EMUSTATE(g_zipgs_unlock), EMUSTATE(g_zipgs_reg_c059), EMUSTATE(g_zipgs_reg_c05a), EMUSTATE(g_zipgs_reg_c05b), EMUSTATE(g_zipgs_reg_c05c), { 0, 0, } }; extern double g_paddle_trig_dcycs; extern double g_last_vbl_dcycs; Emustate_dbllist g_emustate_dbllist[] = { EMUSTATE(g_paddle_trig_dcycs), EMUSTATE(g_last_vbl_dcycs), { 0, 0, } }; extern word32 g_mem_size_total; Emustate_word32list g_emustate_word32list[] = { EMUSTATE(g_mem_size_total), { 0, 0, } }; #define UNIMPL_READ \ halt_printf("UNIMP READ to addr %08x\n", loc); \ return 0; #define UNIMPL_WRITE \ halt_printf("UNIMP WRITE to addr %08x, val: %04x\n", loc, val); \ return; void fixup_brks() { word32 page; word32 tmp, tmp2; Pg_info val; int is_wr_only; int i, num; num = g_num_breakpoints; for(i = 0; i < num; i++) { page = (g_breakpts[i] >> 8) & 0xffff; is_wr_only = (g_breakpts[i] >> 24) & 1; if(!is_wr_only) { val = GET_PAGE_INFO_RD(page); tmp = PTR2WORD(val) & 0xff; tmp2 = tmp | BANK_IO_TMP | BANK_BREAK; SET_PAGE_INFO_RD(page, val - tmp + tmp2); } val = GET_PAGE_INFO_WR(page); tmp = PTR2WORD(val) & 0xff; tmp2 = tmp | BANK_IO_TMP | BANK_BREAK; SET_PAGE_INFO_WR(page, val - tmp + tmp2); } } void fixup_hires_on() { if((g_cur_a2_stat & ALL_STAT_ST80) == 0) { return; } fixup_bank0_2000_4000(); fixup_brks(); } void fixup_bank0_2000_4000() { byte *mem0rd; byte *mem0wr; mem0rd = &(g_memory_ptr[0x2000]); mem0wr = mem0rd; if((g_cur_a2_stat & ALL_STAT_ST80) && (g_cur_a2_stat & ALL_STAT_HIRES)){ if(g_cur_a2_stat & ALL_STAT_PAGE2) { mem0rd += 0x10000; mem0wr += 0x10000; if((g_c035_shadow_reg & 0x12) == 0 || (g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } } else if((g_c035_shadow_reg & 0x02) == 0) { mem0wr += BANK_SHADOW; } } else { if(RAMRD) { mem0rd += 0x10000; } if(RAMWRT) { mem0wr += 0x10000; if((g_c035_shadow_reg & 0x12) == 0 || (g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } } else if((g_c035_shadow_reg & 0x02) == 0) { mem0wr += BANK_SHADOW; } } fixup_any_bank_any_page(0x20, 0x20, mem0rd, mem0wr); } void fixup_bank0_0400_0800() { byte *mem0rd; byte *mem0wr; int shadow; mem0rd = &(g_memory_ptr[0x400]); mem0wr = mem0rd; shadow = BANK_SHADOW; if(g_cur_a2_stat & ALL_STAT_ST80) { if(g_cur_a2_stat & ALL_STAT_PAGE2) { shadow = BANK_SHADOW2; mem0rd += 0x10000; mem0wr += 0x10000; } } else { if(RAMWRT) { shadow = BANK_SHADOW2; mem0wr += 0x10000; } if(RAMRD) { mem0rd += 0x10000; } } if((g_c035_shadow_reg & 0x01) == 0) { mem0wr += shadow; } fixup_any_bank_any_page(0x4, 4, mem0rd, mem0wr); } void fixup_any_bank_any_page(int start_page, int num_pages, byte *mem0rd, byte *mem0wr) { int i; for(i = 0; i < num_pages; i++) { SET_PAGE_INFO_RD(i + start_page, mem0rd); mem0rd += 0x100; } for(i = 0; i < num_pages; i++) { SET_PAGE_INFO_WR(i + start_page, mem0wr); mem0wr += 0x100; } } void fixup_intcx() { byte *rom10000; byte *rom_inc; int no_io_shadow; int off; int start_k; word32 mask; int j, k; rom10000 = &(g_rom_fc_ff_ptr[0x30000]); no_io_shadow = (g_c035_shadow_reg & 0x40); start_k = 0; if(no_io_shadow) { /* if not shadowing, banks 0 and 1 are not affected by intcx */ start_k = 2; } for(k = start_k; k < 4; k++) { off = k; if(k >= 2) { off += (0xe0 - 2); } /* step off through 0x00, 0x01, 0xe0, 0xe1 */ off = off << 8; SET_PAGE_INFO_RD(0xc0 + off, SET_BANK_IO); for(j = 0xc1; j < 0xc8; j++) { mask = 1 << (j & 0xf); if(j < 0xc8) { rom_inc = SET_BANK_IO; if(((g_c02d_int_crom & mask) == 0) || INTCX) { rom_inc = rom10000 + (j << 8); } else { // User-slot rom rom_inc = &(g_rom_cards_ptr[0]) + ((j - 0xc0) << 8); } SET_PAGE_INFO_RD(j + off, rom_inc); } } for(j = 0xc8; j < 0xd0; j++) { /* c800 - cfff */ if(((g_c02d_int_crom & (1 << 3)) == 0) || INTCX) { rom_inc = rom10000 + (j << 8); } else { /* c800 space not necessarily mapped */ /* just map in ROM */ rom_inc = rom10000 + (j << 8); } SET_PAGE_INFO_RD(j + off, rom_inc); } for(j = 0xc0; j < 0xd0; j++) { SET_PAGE_INFO_WR(j + off, SET_BANK_IO); } } if(!no_io_shadow) { SET_PAGE_INFO_RD(0xc7, SET_BANK_IO); /* smartport */ } fixup_brks(); } void fixup_wrdefram(int new_wrdefram) { byte *mem0wr; byte *wrptr; int j; g_c08x_wrdefram = new_wrdefram; if(g_c035_shadow_reg & 0x40) { /* do nothing */ return; } /* if shadowing, banks 0 and 1 are affected by wrdefram */ mem0wr = &(g_memory_ptr[0]); if(!new_wrdefram) { mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); } wrptr = mem0wr + 0x1e000; for(j = 0x1e0; j < 0x200; j++) { SET_PAGE_INFO_WR(j, wrptr); wrptr += 0x100; } wrptr = mem0wr + 0x0e000; if(ALTZP) { wrptr += 0x10000; } for(j = 0xe0; j < 0x100; j++) { SET_PAGE_INFO_WR(j, wrptr); wrptr += 0x100; } wrptr = mem0wr + 0x1d000; if(! LCBANK2) { wrptr -= 0x1000; } for(j = 0x1d0; j < 0x1e0; j++) { SET_PAGE_INFO_WR(j, wrptr); wrptr += 0x100; } wrptr = mem0wr + 0xd000; if(! LCBANK2) { wrptr -= 0x1000; } if(ALTZP) { wrptr += 0x10000; } for(j = 0xd0; j < 0xe0; j++) { SET_PAGE_INFO_WR(j, wrptr); wrptr += 0x100; } fixup_brks(); } void fixup_st80col(double dcycs) { int cur_a2_stat; cur_a2_stat = g_cur_a2_stat; fixup_bank0_0400_0800(); if(cur_a2_stat & ALL_STAT_HIRES) { /* fixup no matter what PAGE2 since PAGE2 and RAMRD/WR */ /* can work against each other */ fixup_bank0_2000_4000(); } if(cur_a2_stat & ALL_STAT_PAGE2) { change_display_mode(dcycs); } fixup_brks(); } void fixup_altzp() { byte *mem0rd, *mem0wr; int rdrom, c08x_wrdefram; int altzp; altzp = ALTZP; mem0rd = &(g_memory_ptr[0]); if(altzp) { mem0rd += 0x10000; } SET_PAGE_INFO_RD(0, mem0rd); SET_PAGE_INFO_RD(1, mem0rd + 0x100); SET_PAGE_INFO_WR(0, mem0rd); SET_PAGE_INFO_WR(1, mem0rd + 0x100); mem0rd = &(g_memory_ptr[0xd000]); mem0wr = mem0rd; c08x_wrdefram = g_c08x_wrdefram; rdrom = RDROM; if(g_c035_shadow_reg & 0x40) { if(ALTZP) { mem0rd += 0x10000; } fixup_any_bank_any_page(0xd0, 0x10, mem0rd - 0x1000, mem0rd - 0x1000); c08x_wrdefram = 1; rdrom = 0; } else { if(!c08x_wrdefram) { mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); } if(ALTZP) { mem0rd += 0x10000; mem0wr += 0x10000; } if(! LCBANK2) { mem0rd -= 0x1000; mem0wr -= 0x1000; } if(rdrom) { mem0rd = &(g_rom_fc_ff_ptr[0x3d000]); } fixup_any_bank_any_page(0xd0, 0x10, mem0rd, mem0wr); } mem0rd = &(g_memory_ptr[0xe000]); mem0wr = mem0rd; if(!c08x_wrdefram) { mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); } if(ALTZP) { mem0rd += 0x10000; mem0wr += 0x10000; } if(rdrom) { mem0rd = &(g_rom_fc_ff_ptr[0x3e000]); } fixup_any_bank_any_page(0xe0, 0x20, mem0rd, mem0wr); /* No need for fixup_brks since called from set_statereg() */ } void fixup_page2(double dcycs) { if((g_cur_a2_stat & ALL_STAT_ST80)) { fixup_bank0_0400_0800(); if((g_cur_a2_stat & ALL_STAT_HIRES)) { fixup_bank0_2000_4000(); } } else { change_display_mode(dcycs); } } void fixup_ramrd() { byte *mem0rd; int cur_a2_stat; int j; cur_a2_stat = g_cur_a2_stat; if((cur_a2_stat & ALL_STAT_ST80) == 0) { fixup_bank0_0400_0800(); } if( ((cur_a2_stat & ALL_STAT_ST80) == 0) || ((cur_a2_stat & ALL_STAT_HIRES) == 0) ) { fixup_bank0_2000_4000(); } mem0rd = &(g_memory_ptr[0x0000]); if(RAMRD) { mem0rd += 0x10000; } SET_PAGE_INFO_RD(2, mem0rd + 0x200); SET_PAGE_INFO_RD(3, mem0rd + 0x300); for(j = 8; j < 0x20; j++) { SET_PAGE_INFO_RD(j, mem0rd + j*0x100); } for(j = 0x40; j < 0xc0; j++) { SET_PAGE_INFO_RD(j, mem0rd + j*0x100); } /* No need for fixup_brks since only called from set_statereg() */ } void fixup_ramwrt() { byte *mem0wr; int cur_a2_stat; int shadow; int ramwrt; int j; cur_a2_stat = g_cur_a2_stat; if((cur_a2_stat & ALL_STAT_ST80) == 0) { fixup_bank0_0400_0800(); } if( ((cur_a2_stat & ALL_STAT_ST80) == 0) || ((cur_a2_stat & ALL_STAT_HIRES) == 0) ) { fixup_bank0_2000_4000(); } mem0wr = &(g_memory_ptr[0x0000]); ramwrt = RAMWRT; if(ramwrt) { mem0wr += 0x10000; } SET_PAGE_INFO_WR(2, mem0wr + 0x200); SET_PAGE_INFO_WR(3, mem0wr + 0x300); shadow = BANK_SHADOW; if(ramwrt) { shadow = BANK_SHADOW2; } if( ((g_c035_shadow_reg & 0x20) != 0) || ((g_rom_version < 3) && !g_user_page2_shadow)) { shadow = 0; } for(j = 8; j < 0x0c; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); } for(j = 0xc; j < 0x20; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100); } shadow = 0; if(ramwrt) { if((g_c035_shadow_reg & 0x14) == 0 || (g_c035_shadow_reg & 0x08) == 0) { shadow = BANK_SHADOW2; } } else if((g_c035_shadow_reg & 0x04) == 0) { shadow = BANK_SHADOW; } for(j = 0x40; j < 0x60; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); } shadow = 0; if(ramwrt && (g_c035_shadow_reg & 0x08) == 0) { /* shr shadowing */ shadow = BANK_SHADOW2; } for(j = 0x60; j < 0xa0; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); } for(j = 0xa0; j < 0xc0; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100); } /* No need for fixup_brks() since only called from set_statereg() */ } void fixup_lcbank2() { byte *mem0rd, *mem0wr; int lcbank2, c08x_wrdefram, rdrom; int off; int k; for(k = 0; k < 4; k++) { off = k; if(k >= 2) { off += (0xe0 - 2); } /* step off through 0x00, 0x01, 0xe0, 0xe1 */ if(k < 2) { mem0rd = &(g_memory_ptr[k << 16]); } else { mem0rd = &(g_slow_memory_ptr[(k & 1) << 16]); } if((k == 0) && ALTZP) { mem0rd += 0x10000; } lcbank2 = LCBANK2; c08x_wrdefram = g_c08x_wrdefram; rdrom = RDROM; if((k < 2) && (g_c035_shadow_reg & 0x40)) { lcbank2 = 0; c08x_wrdefram = 1; rdrom = 0; } if(! lcbank2) { mem0rd -= 0x1000; /* lcbank1, use 0xc000-cfff */ } mem0wr = mem0rd; if((k < 2) && !c08x_wrdefram) { mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); } if((k < 2) && rdrom) { mem0rd = &(g_rom_fc_ff_ptr[0x30000]); } fixup_any_bank_any_page(off*0x100 + 0xd0, 0x10, mem0rd + 0xd000, mem0wr + 0xd000); } /* No need for fixup_brks() since only called from set_statereg(), */ /* or from other routines which will handle it */ } void fixup_rdrom() { byte *mem0rd; int j, k; /* fixup_lcbank2 handles 0xd000-dfff for rd & wr*/ fixup_lcbank2(); for(k = 0; k < 2; k++) { /* k is the bank */ mem0rd = &(g_memory_ptr[k << 16]); if((k == 0) && ALTZP) { mem0rd += 0x10000; } if((g_c035_shadow_reg & 0x40) == 0) { if(RDROM) { mem0rd = &(g_rom_fc_ff_ptr[0x30000]); } } for(j = 0xe0; j < 0x100; j++) { SET_PAGE_INFO_RD(j + k*0x100, mem0rd + j*0x100); } } /* No need for fixup_brks() since only called from set_statereg() */ } void set_statereg(double dcycs, int val) { int xor; xor = val ^ g_c068_statereg; g_c068_statereg = val; if(xor == 0) { return; } if(xor & 0x80) { /* altzp */ fixup_altzp(); } if(xor & 0x40) { /* page2 */ g_cur_a2_stat = (g_cur_a2_stat & ~ALL_STAT_PAGE2) | (val & ALL_STAT_PAGE2); fixup_page2(dcycs); } if(xor & 0x20) { /* RAMRD */ fixup_ramrd(); } if(xor & 0x10) { /* RAMWRT */ fixup_ramwrt(); } if(xor & 0x08) { /* RDROM */ fixup_rdrom(); } if(xor & 0x04) { /* LCBANK2 */ fixup_lcbank2(); } if(xor & 0x02) { /* ROMBANK */ halt_printf("Just set rombank = %d\n", ROMB); } if(xor & 0x01) { fixup_intcx(); } if(xor) { fixup_brks(); } } void fixup_shadow_txt1() { byte *mem0wr; int j; fixup_bank0_0400_0800(); mem0wr = &(g_memory_ptr[0x10000]); if((g_c035_shadow_reg & 0x01) == 0) { mem0wr += BANK_SHADOW2; } for(j = 4; j < 8; j++) { SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); } } void fixup_shadow_txt2() { byte *mem0wr; int shadow; int j; /* bank 0 */ mem0wr = &(g_memory_ptr[0x00000]); shadow = BANK_SHADOW; if(RAMWRT) { mem0wr += 0x10000; shadow = BANK_SHADOW2; } if(((g_c035_shadow_reg & 0x20) == 0) && ((g_rom_version >= 3) || g_user_page2_shadow)) { mem0wr += shadow; } for(j = 8; j < 0xc; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100); } /* and bank 1 */ mem0wr = &(g_memory_ptr[0x10000]); if(((g_c035_shadow_reg & 0x20) == 0) && ((g_rom_version >= 3) || g_user_page2_shadow)) { mem0wr += BANK_SHADOW2; } for(j = 8; j < 0xc; j++) { SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); } } void fixup_shadow_hires1() { byte *mem0wr; int j; fixup_bank0_2000_4000(); /* and bank 1 */ mem0wr = &(g_memory_ptr[0x10000]); if((g_c035_shadow_reg & 0x12) == 0 || (g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } for(j = 0x20; j < 0x40; j++) { SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); } } void fixup_shadow_hires2() { byte *mem0wr; int j; /* bank 0 */ mem0wr = &(g_memory_ptr[0x00000]); if(RAMWRT) { mem0wr += 0x10000; if((g_c035_shadow_reg & 0x14) == 0 || (g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } } else if((g_c035_shadow_reg & 0x04) == 0) { mem0wr += BANK_SHADOW; } for(j = 0x40; j < 0x60; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100); } /* and bank 1 */ mem0wr = &(g_memory_ptr[0x10000]); if((g_c035_shadow_reg & 0x14) == 0 || (g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } for(j = 0x40; j < 0x60; j++) { SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); } } void fixup_shadow_shr() { byte *mem0wr; int j; /* bank 0, only pages 0x60 - 0xa0 */ mem0wr = &(g_memory_ptr[0x00000]); if(RAMWRT) { mem0wr += 0x10000; if((g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } } for(j = 0x60; j < 0xa0; j++) { SET_PAGE_INFO_WR(j, mem0wr + j*0x100); } /* and bank 1, only pages 0x60 - 0xa0 */ mem0wr = &(g_memory_ptr[0x10000]); if((g_c035_shadow_reg & 0x8) == 0) { mem0wr += BANK_SHADOW2; } for(j = 0x60; j < 0xa0; j++) { SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); } } void fixup_shadow_iolc() { byte *mem0rd; int k; if(g_c035_shadow_reg & 0x40) { /* Disable language card area */ for(k = 0; k < 2; k++) { mem0rd = &(g_memory_ptr[k << 16]); fixup_any_bank_any_page((k << 8) + 0xc0, 0x10, mem0rd + 0xd000, mem0rd + 0xd000); if(k == 0 && ALTZP) { mem0rd += 0x10000; } fixup_any_bank_any_page((k << 8) + 0xd0, 0x10, mem0rd + 0xc000, mem0rd + 0xc000); fixup_any_bank_any_page((k << 8) + 0xe0, 0x20, mem0rd + 0xe000, mem0rd + 0xe000); } } else { /* 0xc000 area */ fixup_intcx(); /* 0xd000 area */ /* fixup_lcbank2(); -- not needed since fixup_rdrom does it */ /* Fix 0xd000-0xffff for reads, banks 0 and 1 */ fixup_rdrom(); /* which calls fixup_lcbank2 */ /* Fix 0xd000-0xffff for writes, banks 0 and 1 */ fixup_wrdefram(g_c08x_wrdefram); } } void update_shadow_reg(int val) { int xor; if(g_c035_shadow_reg == val) { return; } xor = g_c035_shadow_reg ^ val; g_c035_shadow_reg = val; if(xor & 8) { fixup_shadow_hires1(); fixup_shadow_hires2(); fixup_shadow_shr(); xor = xor & (~0x16); } if(xor & 0x10) { fixup_shadow_hires1(); fixup_shadow_hires2(); xor = xor & (~0x6); } if(xor & 2) { fixup_shadow_hires1(); } if(xor & 4) { fixup_shadow_hires2(); } if(xor & 1) { fixup_shadow_txt1(); } if((xor & 0x20) && ((g_rom_version >= 3) || g_user_page2_shadow)) { fixup_shadow_txt2(); } if(xor & 0x40) { fixup_shadow_iolc(); } if(xor) { fixup_brks(); } } void fixup_shadow_all_banks() { byte *mem0rd; int shadow; int num_banks; int j, k; /* Assume Ninja Force Megademo */ /* only do banks 3 - num_banks by 2, shadowing into e1 */ shadow = 0; if((g_c036_val_speed & 0x10) && ((g_c035_shadow_reg & 0x08) == 0)) { shadow = BANK_SHADOW2; } num_banks = g_mem_size_total >> 16; for(k = 3; k < num_banks; k += 2) { mem0rd = &(g_memory_ptr[k*0x10000 + 0x2000]) + shadow; for(j = 0x20; j < 0xa0; j++) { SET_PAGE_INFO_WR(k*0x100 + j, mem0rd); mem0rd += 0x100; } } fixup_brks(); } void setup_pageinfo() { byte *mem0rd; word32 mem_size_pages; /* first, set all of memory to point to itself */ mem_size_pages = g_mem_size_total >> 8; mem0rd = &(g_memory_ptr[0]); fixup_any_bank_any_page(0, mem_size_pages, mem0rd, mem0rd); /* mark unused memory as BAD_MEM */ fixup_any_bank_any_page(mem_size_pages, 0xfc00-mem_size_pages, BANK_BAD_MEM, BANK_BAD_MEM); fixup_shadow_all_banks(); /* ROM */ mem0rd = &(g_rom_fc_ff_ptr[0]); fixup_any_bank_any_page(0xfc00, 0x400, mem0rd, mem0rd + (BANK_IO_TMP | BANK_IO2_TMP)); /* banks e0, e1 */ mem0rd = &(g_slow_memory_ptr[0]); fixup_any_bank_any_page(0xe000, 0x04, mem0rd + 0x0000, mem0rd + 0x0000); fixup_any_bank_any_page(0xe004, 0x08, mem0rd + 0x0400, mem0rd + 0x0400 + BANK_SHADOW); fixup_any_bank_any_page(0xe00c, 0x14, mem0rd + 0x0c00, mem0rd + 0x0c00); fixup_any_bank_any_page(0xe020, 0x40, mem0rd + 0x2000, mem0rd + 0x2000 + BANK_SHADOW); fixup_any_bank_any_page(0xe060, 0xa0, mem0rd + 0x6000, mem0rd + 0x6000); mem0rd = &(g_slow_memory_ptr[0x10000]); fixup_any_bank_any_page(0xe100, 0x04, mem0rd + 0x0000, mem0rd + 0x0000); fixup_any_bank_any_page(0xe104, 0x08, mem0rd + 0x0400, mem0rd + 0x0400 + BANK_SHADOW2); fixup_any_bank_any_page(0xe10c, 0x14, mem0rd + 0x0c00, mem0rd + 0x0c00); fixup_any_bank_any_page(0xe120, 0x80, mem0rd + 0x2000, mem0rd + 0x2000 + BANK_SHADOW2); fixup_any_bank_any_page(0xe1a0, 0x60, mem0rd + 0xa000, mem0rd + 0xa000); fixup_intcx(); /* correct banks 0xe0,0xe1, 0xc000-0xcfff area */ fixup_lcbank2(); /* correct 0xd000-0xdfff area */ fixup_bank0_2000_4000(); fixup_bank0_0400_0800(); fixup_wrdefram(g_c08x_wrdefram); fixup_altzp(); fixup_ramrd(); fixup_ramwrt(); fixup_rdrom(); fixup_shadow_txt1(); fixup_shadow_txt2(); fixup_shadow_hires1(); fixup_shadow_hires2(); fixup_shadow_shr(); fixup_shadow_iolc(); fixup_brks(); } void show_bankptrs_bank0rdwr() { show_bankptrs(0); show_bankptrs(1); show_bankptrs(0xe0); show_bankptrs(0xe1); printf("statereg: %02x\n", g_c068_statereg); } void show_bankptrs(int bnk) { int i; Pg_info rd, wr; byte *ptr_rd, *ptr_wr; printf("g_memory_ptr: %p, dummy_mem: %p, slow_mem_ptr: %p\n", g_memory_ptr, g_dummy_memory1_ptr, g_slow_memory_ptr); printf("g_rom_fc_ff_ptr: %p\n", g_rom_fc_ff_ptr); printf("Showing bank_info array for %02x\n", bnk); for(i = 0; i < 256; i++) { rd = GET_PAGE_INFO_RD(bnk*0x100 + i); wr = GET_PAGE_INFO_WR(bnk*0x100 + i); ptr_rd = (byte *)rd; ptr_wr = (byte *)wr; printf("%04x rd: ", bnk*256 + i); show_addr(ptr_rd); printf(" wr: "); show_addr(ptr_wr); printf("\n"); } } void show_addr(byte *ptr) { word32 mem_size; mem_size = g_mem_size_total; if(ptr >= g_memory_ptr && ptr < &g_memory_ptr[mem_size]) { printf("%p--memory[%06x]", ptr, (word32)(ptr - g_memory_ptr)); } else if(ptr >= g_rom_fc_ff_ptr && ptr < &g_rom_fc_ff_ptr[256*1024]) { printf("%p--rom_fc_ff[%06x]", ptr, (word32)(ptr - g_rom_fc_ff_ptr)); } else if(ptr >= g_slow_memory_ptr && ptr<&g_slow_memory_ptr[128*1024]){ printf("%p--slow_memory[%06x]", ptr, (word32)(ptr - g_slow_memory_ptr)); } else if(ptr >=g_dummy_memory1_ptr && ptr < &g_dummy_memory1_ptr[256]){ printf("%p--dummy_memory[%06x]", ptr, (word32)(ptr - g_dummy_memory1_ptr)); } else { printf("%p--unknown", ptr); } } #define CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc) \ dcycs = g_last_vbl_dcycs + *cyc_ptr; int io_read(word32 loc, double *cyc_ptr) { double dcycs; word64 word64_tmp; #if 0 double fcyc, new_fcyc; #endif word32 mask; int new_lcbank2; int new_wrdefram; int tmp; int i; CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc); /* IO space */ switch((loc >> 8) & 0xf) { case 0: /* 0xc000 - 0xc0ff */ switch(loc & 0xff) { /* 0xc000 - 0xc00f */ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: return(adb_read_c000()); /* 0xc010 - 0xc01f */ case 0x10: /* c010 */ return(adb_access_c010()); case 0x11: /* c011 = RDLCBANK2 */ return IOR(LCBANK2); case 0x12: /* c012= RDLCRAM */ return IOR(!RDROM); case 0x13: /* c013=rdramd */ return IOR(RAMRD); case 0x14: /* c014=rdramwrt */ return IOR(RAMWRT); case 0x15: /* c015 = INTCX */ return IOR(INTCX); case 0x16: /* c016: ALTZP */ return IOR(ALTZP); case 0x17: /* c017: rdc3rom */ return IOR(g_c02d_int_crom & (1 << 3)); case 0x18: /* c018: rd80c0l */ return IOR((g_cur_a2_stat & ALL_STAT_ST80)); case 0x19: /* c019: rdvblbar */ tmp = in_vblank(dcycs); return IOR(tmp); case 0x1a: /* c01a: rdtext */ return IOR(g_cur_a2_stat & ALL_STAT_TEXT); case 0x1b: /* c01b: rdmix */ return IOR(g_cur_a2_stat & ALL_STAT_MIX_T_GR); case 0x1c: /* c01c: rdpage2 */ return IOR(g_cur_a2_stat & ALL_STAT_PAGE2); case 0x1d: /* c01d: rdhires */ return IOR(g_cur_a2_stat & ALL_STAT_HIRES); case 0x1e: /* c01e: altcharset on? */ return IOR(g_cur_a2_stat & ALL_STAT_ALTCHARSET); case 0x1f: /* c01f: rd80vid */ return IOR(g_cur_a2_stat & ALL_STAT_VID80); /* 0xc020 - 0xc02f */ case 0x20: /* 0xc020 */ /* Click cassette port */ return 0x00; case 0x21: /* 0xc021 */ /* Not documented, but let's return COLOR_C021 */ return IOR(g_cur_a2_stat & ALL_STAT_COLOR_C021); case 0x22: /* 0xc022 */ return (g_cur_a2_stat >> BIT_ALL_STAT_BG_COLOR) & 0xff; case 0x23: /* 0xc023 */ return g_c023_val; case 0x24: /* 0xc024 */ return mouse_read_c024(dcycs); case 0x25: /* 0xc025 */ return adb_read_c025(); case 0x26: /* 0xc026 */ return adb_read_c026(); case 0x27: /* 0xc027 */ return adb_read_c027(); case 0x28: /* 0xc028 */ UNIMPL_READ; case 0x29: /* 0xc029 */ return((g_cur_a2_stat & 0xa0) | g_c029_val_some); case 0x2a: /* 0xc02a */ #if 0 printf("Reading c02a...returning 0\n"); #endif return 0; case 0x2b: /* 0xc02b */ return g_c02b_val; case 0x2c: /* 0xc02c */ /* printf("reading c02c, returning 0\n"); */ return 0; case 0x2d: /* 0xc02d */ tmp = g_c02d_int_crom; return tmp; case 0x2e: /* 0xc02e */ case 0x2f: /* 0xc02f */ return read_vid_counters(loc, dcycs); /* 0xc030 - 0xc03f */ case 0x30: /* 0xc030 */ /* click speaker */ return doc_read_c030(dcycs); case 0x31: /* 0xc031 */ /* 3.5" control */ return g_c031_disk35; case 0x32: /* 0xc032 */ /* scan int */ return 0; case 0x33: /* 0xc033 = CLOCKDATA*/ return g_c033_data; case 0x34: /* 0xc034 = CLOCKCTL */ return g_c034_val; case 0x35: /* 0xc035 */ return g_c035_shadow_reg; case 0x36: /* 0xc036 = CYAREG */ return g_c036_val_speed; case 0x37: /* 0xc037 */ return 0; case 0x38: /* 0xc038 */ return scc_read_reg(1, dcycs); case 0x39: /* 0xc039 */ return scc_read_reg(0, dcycs); case 0x3a: /* 0xc03a */ return scc_read_data(1, dcycs); case 0x3b: /* 0xc03b */ return scc_read_data(0, dcycs); case 0x3c: /* 0xc03c */ /* doc control */ return doc_read_c03c(dcycs); case 0x3d: /* 0xc03d */ return doc_read_c03d(dcycs); case 0x3e: /* 0xc03e */ return (g_c03ef_doc_ptr & 0xff); case 0x3f: /* 0xc03f */ return (g_c03ef_doc_ptr >> 8); /* 0xc040 - 0xc04f */ case 0x40: /* 0xc040 */ /* cassette */ return 0; case 0x41: /* 0xc041 */ return g_c041_val; case 0x45: /* 0xc045 */ halt_printf("Mega II mouse read: c045\n"); return 0; case 0x46: /* 0xc046 */ tmp = g_c046_val; g_c046_val = (tmp & 0xbf) + ((tmp & 0x80) >> 1); return tmp; case 0x47: /* 0xc047 */ remove_irq(IRQ_PENDING_C046_25SEC | IRQ_PENDING_C046_VBL); g_c046_val &= 0xe7; /* clear vbl_int, 1/4sec int*/ return 0; case 0x42: /* 0xc042 */ case 0x43: /* 0xc043 */ return 0; case 0x4f: /* 0xc04f */ /* for information on c04f, see: */ /* www.sheppyware.net/tech/hardware/softswitches.html */ /* write to $c04f to start. Then read $c04f to get */ /* emulator ($16=sweet16, $fe=bernie II). */ /* Then read again to get version: $21 == 2.1 */ switch(g_em_emubyte_cnt) { case 1: g_em_emubyte_cnt = 2; return 'K'; case 2: g_em_emubyte_cnt = 0; tmp = g_kegs_version_str[0] - '0'; i = g_kegs_version_str[2] - '0'; return ((tmp & 0xf) << 4) + (i & 0xf); default: g_em_emubyte_cnt = 0; return 0; } case 0x44: /* 0xc044 */ case 0x48: /* 0xc048 */ case 0x49: /* 0xc049 */ case 0x4a: /* 0xc04a */ case 0x4b: /* 0xc04b */ case 0x4c: /* 0xc04c */ case 0x4d: /* 0xc04d */ case 0x4e: /* 0xc04e */ UNIMPL_READ; /* 0xc050 - 0xc05f */ case 0x50: /* 0xc050 */ if(g_cur_a2_stat & ALL_STAT_TEXT) { g_cur_a2_stat &= (~ALL_STAT_TEXT); change_display_mode(dcycs); } return float_bus(dcycs); case 0x51: /* 0xc051 */ if((g_cur_a2_stat & ALL_STAT_TEXT) == 0) { g_cur_a2_stat |= (ALL_STAT_TEXT); change_display_mode(dcycs); } return float_bus(dcycs); case 0x52: /* 0xc052 */ if(g_cur_a2_stat & ALL_STAT_MIX_T_GR) { g_cur_a2_stat &= (~ALL_STAT_MIX_T_GR); change_display_mode(dcycs); } return float_bus(dcycs); case 0x53: /* 0xc053 */ if((g_cur_a2_stat & ALL_STAT_MIX_T_GR) == 0) { g_cur_a2_stat |= (ALL_STAT_MIX_T_GR); change_display_mode(dcycs); } return float_bus(dcycs); case 0x54: /* 0xc054 */ set_statereg(dcycs, g_c068_statereg & (~0x40)); return float_bus(dcycs); case 0x55: /* 0xc055 */ set_statereg(dcycs, g_c068_statereg | 0x40); return float_bus(dcycs); case 0x56: /* 0xc056 */ if(g_cur_a2_stat & ALL_STAT_HIRES) { g_cur_a2_stat &= (~ALL_STAT_HIRES); fixup_hires_on(); change_display_mode(dcycs); } return float_bus(dcycs); case 0x57: /* 0xc057 */ if((g_cur_a2_stat & ALL_STAT_HIRES) == 0) { g_cur_a2_stat |= (ALL_STAT_HIRES); fixup_hires_on(); change_display_mode(dcycs); } return float_bus(dcycs); case 0x58: /* 0xc058 */ if(g_zipgs_unlock < 4) { g_c05x_annuncs &= (~1); } return 0; case 0x59: /* 0xc059 */ if(g_zipgs_unlock >= 4) { return g_zipgs_reg_c059; } else { g_c05x_annuncs |= 1; } return 0; case 0x5a: /* 0xc05a */ if(g_zipgs_unlock >= 4) { return g_zipgs_reg_c05a; } else { g_c05x_annuncs &= (~2); } return 0; case 0x5b: /* 0xc05b */ if(g_zipgs_unlock >= 4) { word64_tmp = (word64)dcycs; tmp = (word64_tmp >> 9) & 1; return (tmp << 7) + (g_zipgs_reg_c05b & 0x7f); } else { g_c05x_annuncs |= 2; } return 0; case 0x5c: /* 0xc05c */ if(g_zipgs_unlock >= 4) { return g_zipgs_reg_c05c; } else { g_c05x_annuncs &= (~4); } return 0; case 0x5d: /* 0xc05d */ if(g_zipgs_unlock >= 4) { halt_printf("Reading ZipGS $c05d!\n"); } else { g_c05x_annuncs |= 4; } return 0; case 0x5e: /* 0xc05e */ if(g_zipgs_unlock >= 4) { halt_printf("Reading ZipGS $c05e!\n"); } else if(g_cur_a2_stat & ALL_STAT_ANNUNC3) { g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); change_display_mode(dcycs); } return 0; case 0x5f: /* 0xc05f */ if(g_zipgs_unlock >= 4) { halt_printf("Reading ZipGS $c05f!\n"); } else if((g_cur_a2_stat & ALL_STAT_ANNUNC3) == 0) { g_cur_a2_stat |= (ALL_STAT_ANNUNC3); change_display_mode(dcycs); } return 0; /* 0xc060 - 0xc06f */ case 0x60: /* 0xc060 */ return IOR(g_paddle_buttons & 8); case 0x61: /* 0xc061 */ return IOR(adb_is_cmd_key_down() || g_paddle_buttons & 1); case 0x62: /* 0xc062 */ return IOR(adb_is_option_key_down() || g_paddle_buttons & 2); case 0x63: /* 0xc063 */ return IOR(g_paddle_buttons & 4); case 0x64: /* 0xc064 */ return read_paddles(dcycs, 0); case 0x65: /* 0xc065 */ return read_paddles(dcycs, 1); case 0x66: /* 0xc066 */ return read_paddles(dcycs, 2); case 0x67: /* 0xc067 */ return read_paddles(dcycs, 3); case 0x68: /* 0xc068 = STATEREG */ return g_c068_statereg; case 0x69: /* 0xc069 */ /* Reserved reg, return 0 */ return 0; case 0x6a: /* 0xc06a */ case 0x6b: /* 0xc06b */ case 0x6c: /* 0xc06c */ case 0x6d: /* 0xc06d */ case 0x6e: /* 0xc06e */ case 0x6f: /* 0xc06f */ UNIMPL_READ; /* 0xc070 - 0xc07f */ case 0x70: /* c070 */ paddle_trigger(dcycs); return 0; case 0x71: /* 0xc071 */ case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: return g_rom_fc_ff_ptr[3*65536 + 0xc000 + (loc & 0xff)]; /* 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: new_lcbank2 = ((loc & 0x8) >> 1) ^ 0x4; new_wrdefram = (loc & 1); if(new_wrdefram != g_c08x_wrdefram) { fixup_wrdefram(new_wrdefram); } switch(loc & 0x3) { case 0x1: /* 0xc081 */ case 0x2: /* 0xc082 */ /* Read rom, set lcbank2 */ set_statereg(dcycs, (g_c068_statereg & ~(0x04))| (new_lcbank2 | 0x08)); break; case 0x0: /* 0xc080 */ case 0x3: /* 0xc083 */ /* Read ram (clear RDROM), set lcbank2 */ set_statereg(dcycs, (g_c068_statereg & ~(0x0c))| (new_lcbank2)); break; } return float_bus(dcycs); /* 0xc090 - 0xc09f */ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: /* UNIMPL_READ; */ return 0; /* 0xc0a0 - 0xc0af */ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: return 0; /* UNIMPL_READ; */ /* 0xc0b0 - 0xc0bf */ case 0xb0: /* c0b0: female voice tool033 look at this */ return 0; case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: /* UNIMPL_READ; */ return 0; /* c0b8: Second Sight card stuff: return 0 */ case 0xb8: return 0; break; /* 0xc0c0 - 0xc0cf */ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: return 0; /* 0xc0d0 - 0xc0df */ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: return 0; /* 0xc0e0 - 0xc0ef */ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xed: case 0xee: case 0xef: return read_iwm(loc, dcycs); case 0xec: return iwm_read_c0ec(dcycs); /* 0xc0f0 - 0xc0ff */ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: return 0; default: printf("loc: %04x bad\n", loc); UNIMPL_READ; } case 1: case 2: case 3: case 4: case 5: case 6: /* c100 - c6ff */ mask = (1 << ((loc >> 8) & 7)); if(INTCX || ((g_c02d_int_crom & mask) == 0)) { return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); } return float_bus(dcycs); case 7: /* c700 */ if(INTCX || ((g_c02d_int_crom & (1 << 7)) == 0)) { return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); } tmp = g_rom_fc_ff_ptr[0x3c500 + (loc & 0xff)]; if((loc & 0xff) == 0xfb) { tmp = tmp & 0xbf; /* clear bit 6 for ROM 03 */ } return tmp; case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: if(INTCX || ((g_c02d_int_crom & (1 << 3)) == 0)) { return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); } UNIMPL_READ; case 0xf: if(INTCX || ((g_c02d_int_crom & (1 << 3)) == 0)) { return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); } if((loc & 0xfff) == 0xfff) { return g_rom_fc_ff_ptr[0x3cfff]; } UNIMPL_READ; } halt_printf("io_read: hit end, loc: %06x\n", loc); return 0xff; } void io_write(word32 loc, int val, double *cyc_ptr) { double dcycs; #if 0 double fcyc, new_fcyc; #endif int new_tmp; int new_lcbank2; int new_wrdefram; int tmp; int fixup; CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc); val = val & 0xff; switch((loc >> 8) & 0xf) { case 0: /* 0xc000 - 0xc0ff */ switch(loc & 0xff) { /* 0xc000 - 0xc00f */ case 0x00: /* 0xc000 */ if(g_cur_a2_stat & ALL_STAT_ST80) { g_cur_a2_stat &= (~ALL_STAT_ST80); fixup_st80col(dcycs); } return; case 0x01: /* 0xc001 */ if((g_cur_a2_stat & ALL_STAT_ST80) == 0) { g_cur_a2_stat |= (ALL_STAT_ST80); fixup_st80col(dcycs); } return; case 0x02: /* 0xc002 */ set_statereg(dcycs, g_c068_statereg & ~0x20); return; case 0x03: /* 0xc003 */ set_statereg(dcycs, g_c068_statereg | 0x20); return; case 0x04: /* 0xc004 */ set_statereg(dcycs, g_c068_statereg & ~0x10); return; case 0x05: /* 0xc005 */ set_statereg(dcycs, g_c068_statereg | 0x10); return; case 0x06: /* 0xc006 */ set_statereg(dcycs, g_c068_statereg & ~0x01); return; case 0x07: /* 0xc007 */ set_statereg(dcycs, g_c068_statereg | 0x01); return; case 0x08: /* 0xc008 */ set_statereg(dcycs, g_c068_statereg & ~0x80); return; case 0x09: /* 0xc009 */ set_statereg(dcycs, g_c068_statereg | 0x80); return; case 0x0a: /* 0xc00a */ tmp = 1 << 3; if((g_c02d_int_crom & tmp) != 0) { g_c02d_int_crom &= ~tmp; fixup_intcx(); } return; case 0x0b: /* 0xc00b */ tmp = 1 << 3; if((g_c02d_int_crom & tmp) == 0) { g_c02d_int_crom |= tmp; fixup_intcx(); } return; case 0x0c: /* 0xc00c */ if(g_cur_a2_stat & ALL_STAT_VID80) { g_cur_a2_stat &= (~ALL_STAT_VID80); change_display_mode(dcycs); } return; case 0x0d: /* 0xc00d */ if((g_cur_a2_stat & ALL_STAT_VID80) == 0) { g_cur_a2_stat |= (ALL_STAT_VID80); change_display_mode(dcycs); } return; case 0x0e: /* 0xc00e */ if(g_cur_a2_stat & ALL_STAT_ALTCHARSET) { g_cur_a2_stat &= (~ALL_STAT_ALTCHARSET); change_display_mode(dcycs); } return; case 0x0f: /* 0xc00f */ if((g_cur_a2_stat & ALL_STAT_ALTCHARSET) == 0) { g_cur_a2_stat |= (ALL_STAT_ALTCHARSET); change_display_mode(dcycs); } return; /* 0xc010 - 0xc01f */ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: adb_access_c010(); return; /* 0xc020 - 0xc02f */ case 0x20: /* 0xc020 */ /* WRITE CASSETTE?? */ return; case 0x21: /* 0xc021 */ new_tmp = ((val >> 7) & 1) << (31 - BIT_ALL_STAT_COLOR_C021); if((g_cur_a2_stat & ALL_STAT_COLOR_C021) != new_tmp) { g_cur_a2_stat ^= new_tmp; change_display_mode(dcycs); } return; case 0x22: /* 0xc022 */ /* change text color */ tmp = (g_cur_a2_stat >> BIT_ALL_STAT_BG_COLOR) & 0xff; if(val != tmp) { /* change text/bg color! */ g_cur_a2_stat &= ~(ALL_STAT_TEXT_COLOR | ALL_STAT_BG_COLOR); g_cur_a2_stat += (val << BIT_ALL_STAT_BG_COLOR); change_display_mode(dcycs); } return; case 0x23: /* 0xc023 */ if((val & 0x19) != 0) { halt_printf("c023 write of %02x!!!\n", val); } tmp = (g_c023_val & 0x70) | (val & 0x0f); if((tmp & 0x22) == 0x22) { add_irq(IRQ_PENDING_C023_SCAN); } if(!(tmp & 2)) { remove_irq(IRQ_PENDING_C023_SCAN); } if((tmp & 0x44) == 0x44) { add_irq(IRQ_PENDING_C023_1SEC); } if(!(tmp & 0x4)) { remove_irq(IRQ_PENDING_C023_1SEC); } if(g_irq_pending & (IRQ_PENDING_C023_SCAN | IRQ_PENDING_C023_1SEC)) { tmp |= 0x80; } g_c023_val = tmp; return; case 0x24: /* 0xc024 */ /* Write to mouse reg: Throw it away */ return; case 0x26: /* 0xc026 */ adb_write_c026(val); return; case 0x27: /* 0xc027 */ adb_write_c027(val); return; case 0x29: /* 0xc029 */ g_c029_val_some = val & 0x41; if((val & 1) == 0) { halt_printf("c029: %02x\n", val); } new_tmp = val & 0xa0; if(new_tmp != (g_cur_a2_stat & 0xa0)) { g_cur_a2_stat = (g_cur_a2_stat & (~0xa0)) + new_tmp; change_display_mode(dcycs); } return; case 0x2a: /* 0xc02a */ #if 0 printf("Writing c02a with %02x\n", val); #endif return; case 0x2b: /* 0xc02b */ g_c02b_val = val; if(val != 0x08 && val != 0x00) { printf("Writing c02b with %02x\n", val); } return; case 0x2d: /* 0xc02d */ if((val & 0x9) != 0) { halt_printf("Illegal c02d write: %02x!\n", val); } fixup = (val != g_c02d_int_crom); g_c02d_int_crom = val; if(fixup) { vid_printf("Write c02d of %02x\n", val); fixup_intcx(); } return; case 0x28: /* 0xc028 */ case 0x2c: /* 0xc02c */ UNIMPL_WRITE; case 0x25: /* 0xc025 */ /* Space Shark writes to c025--ignore */ case 0x2e: /* 0xc02e */ case 0x2f: /* 0xc02f */ /* Modulae writes to this--just ignore them */ return; break; /* 0xc030 - 0xc03f */ case 0x30: /* 0xc030 */ #if 0 printf("Write speaker?\n"); #endif (void)doc_read_c030(dcycs); return; case 0x31: /* 0xc031 */ tmp = val ^ g_c031_disk35; if(tmp & 0x40) { /* apple35_sel changed, maybe speed change */ set_halt(HALT_EVENT); } g_c031_disk35 = val & 0xc0; return; case 0x32: /* 0xc032 */ tmp = g_c023_val & 0x7f; if(((val & 0x40) == 0) && (tmp & 0x40)) { /* clear 1 sec int */ remove_irq(IRQ_PENDING_C023_1SEC); tmp &= 0xbf; g_c023_val = tmp; } if(((val & 0x20) == 0) && (tmp & 0x20)) { /* clear scan line int */ remove_irq(IRQ_PENDING_C023_SCAN); g_c023_val = tmp & 0xdf; check_for_new_scan_int(dcycs); } if(g_irq_pending & (IRQ_PENDING_C023_1SEC | IRQ_PENDING_C023_SCAN)) { g_c023_val |= 0x80; } if((val & 0x9f) != 0x9f) { irq_printf("c032: wrote %02x!\n", val); } return; case 0x33: /* 0xc033 = CLOCKDATA*/ g_c033_data = val; return; case 0x34: /* 0xc034 = CLOCKCTL */ tmp = val ^ g_c034_val; clock_write_c034(val); if(tmp & 0xf) { change_border_color(dcycs, val & 0xf); } return; case 0x35: /* 0xc035 */ update_shadow_reg(val); return; case 0x36: /* 0xc036 = CYAREG */ tmp = val ^ g_c036_val_speed; g_c036_val_speed = (val & ~0x20); /* clr bit 5 */ if(tmp & 0x80) { /* to recalculate times since speed changing */ set_halt(HALT_EVENT); } if(tmp & 0xf) { /* slot_motor_detect changed */ set_halt(HALT_EVENT); } if((val & 0x60) != 0) { /* for ROM 03, 0x40 is the power-on status */ /* and can be read/write */ if(((val & 0x60) != 0x40) || (g_rom_version < 3)) { g_c036_val_speed &= (~0x60); halt_printf("c036: %2x\n", val); } } if(tmp & 0x10) { /* shadow in all banks! */ if(g_num_shadow_all_banks++ == 0) { printf("Shadowing all banks...This " "must be the NFC Megademo\n"); } fixup_shadow_all_banks(); } return; case 0x37: /* 0xc037 */ /* just ignore, probably someone writing c036 m=0 */ return; case 0x38: /* 0xc038 */ scc_write_reg(1, val, dcycs); return; case 0x39: /* 0xc039 */ scc_write_reg(0, val, dcycs); return; case 0x3a: /* 0xc03a */ scc_write_data(1, val, dcycs); return; case 0x3b: /* 0xc03b */ scc_write_data(0, val, dcycs); return; case 0x3c: /* 0xc03c */ /* doc ctl */ doc_write_c03c(val, dcycs); return; case 0x3d: /* 0xc03d */ /* doc data reg */ doc_write_c03d(val, dcycs); return; case 0x3e: /* 0xc03e */ g_c03ef_doc_ptr = (g_c03ef_doc_ptr & 0xff00) + val; return; case 0x3f: /* 0xc03f */ g_c03ef_doc_ptr = (g_c03ef_doc_ptr & 0xff) + (val << 8); return; /* 0xc040 - 0xc04f */ case 0x41: /* c041 */ g_c041_val = val & 0x1f; if((val & 0xe7) != 0) { halt_printf("write c041: %02x\n", val); } if(!(val & C041_EN_VBL_INTS)) { /* no more vbl interrupt */ remove_irq(IRQ_PENDING_C046_VBL); } if(!(val & C041_EN_25SEC_INTS)) { remove_irq(IRQ_PENDING_C046_25SEC); } return; case 0x46: /* c046 */ /* ignore writes to c046 */ return; case 0x47: /* c047 */ remove_irq(IRQ_PENDING_C046_VBL | IRQ_PENDING_C046_25SEC); g_c046_val &= 0xe7; /* clear vblint, 1/4sec int*/ return; case 0x48: /* c048 */ /* diversitune writes this--ignore it */ return; case 0x42: /* c042 */ case 0x43: /* c043 */ return; case 0x4f: /* c04f */ g_em_emubyte_cnt = 1; return; case 0x40: /* c040 */ case 0x44: /* c044 */ case 0x45: /* c045 */ case 0x49: /* c049 */ case 0x4a: /* c04a */ case 0x4b: /* c04b */ case 0x4c: /* c04c */ case 0x4d: /* c04d */ case 0x4e: /* c04e */ UNIMPL_WRITE; /* 0xc050 - 0xc05f */ case 0x50: /* 0xc050 */ if(g_cur_a2_stat & ALL_STAT_TEXT) { g_cur_a2_stat &= (~ALL_STAT_TEXT); change_display_mode(dcycs); } return; case 0x51: /* 0xc051 */ if((g_cur_a2_stat & ALL_STAT_TEXT) == 0) { g_cur_a2_stat |= (ALL_STAT_TEXT); change_display_mode(dcycs); } return; case 0x52: /* 0xc052 */ if(g_cur_a2_stat & ALL_STAT_MIX_T_GR) { g_cur_a2_stat &= (~ALL_STAT_MIX_T_GR); change_display_mode(dcycs); } return; case 0x53: /* 0xc053 */ if((g_cur_a2_stat & ALL_STAT_MIX_T_GR) == 0) { g_cur_a2_stat |= (ALL_STAT_MIX_T_GR); change_display_mode(dcycs); } return; case 0x54: /* 0xc054 */ set_statereg(dcycs, g_c068_statereg & (~0x40)); return; case 0x55: /* 0xc055 */ set_statereg(dcycs, g_c068_statereg | 0x40); return; case 0x56: /* 0xc056 */ if(g_cur_a2_stat & ALL_STAT_HIRES) { g_cur_a2_stat &= (~ALL_STAT_HIRES); fixup_hires_on(); change_display_mode(dcycs); } return; case 0x57: /* 0xc057 */ if((g_cur_a2_stat & ALL_STAT_HIRES) == 0) { g_cur_a2_stat |= (ALL_STAT_HIRES); fixup_hires_on(); change_display_mode(dcycs); } return; case 0x58: /* 0xc058 */ if(g_zipgs_unlock >= 4) { g_zipgs_reg_c059 &= 0x4; /* last reset cold */ } else { g_c05x_annuncs &= (~1); } return; case 0x59: /* 0xc059 */ if(g_zipgs_unlock >= 4) { g_zipgs_reg_c059 = (val & 0xf8) | (g_zipgs_reg_c059 & 0x7); } else { g_c05x_annuncs |= 1; } return; case 0x5a: /* 0xc05a */ g_c05x_annuncs &= (~2); if((val & 0xf0) == 0x50) { g_zipgs_unlock++; } else if((val & 0xf0) == 0xa0) { g_zipgs_unlock = 0; } else if(g_zipgs_unlock >= 4) { if((g_zipgs_reg_c05b & 0x10) == 0) { /* to recalculate times */ set_halt(HALT_EVENT); } g_zipgs_reg_c05b |= 0x10; // disable } return; case 0x5b: /* 0xc05b */ if(g_zipgs_unlock >= 4) { if((g_zipgs_reg_c05b & 0x10) != 0) { /* to recalculate times */ set_halt(HALT_EVENT); } g_zipgs_reg_c05b &= (~0x10); // enable } else { g_c05x_annuncs |= 2; } return; case 0x5c: /* 0xc05c */ if(g_zipgs_unlock >= 4) { g_zipgs_reg_c05c = val; } else { g_c05x_annuncs &= (~4); } return; case 0x5d: /* 0xc05d */ if(g_zipgs_unlock >= 4) { if(((g_zipgs_reg_c05a ^ val) >= 0x10) && ((g_zipgs_reg_c05b & 0x10) == 0)) { set_halt(HALT_EVENT); } g_zipgs_reg_c05a = val | 0xf; } else { g_c05x_annuncs |= 4; } return; case 0x5e: /* 0xc05e */ if(g_zipgs_unlock >= 4) { /* Zippy writes 0x80 and 0x00 here... */ } else if(g_cur_a2_stat & ALL_STAT_ANNUNC3) { g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); change_display_mode(dcycs); } return; case 0x5f: /* 0xc05f */ if(g_zipgs_unlock >= 4) { halt_printf("Wrote ZipGS $c05f: %02x\n", val); } else if((g_cur_a2_stat & ALL_STAT_ANNUNC3) == 0) { g_cur_a2_stat |= (ALL_STAT_ANNUNC3); change_display_mode(dcycs); } return; /* 0xc060 - 0xc06f */ case 0x60: /* 0xc060 */ case 0x61: /* 0xc061 */ case 0x62: /* 0xc062 */ case 0x63: /* 0xc063 */ case 0x64: /* 0xc064 */ case 0x65: /* 0xc065 */ case 0x66: /* 0xc066 */ case 0x67: /* 0xc067 */ /* all the above do nothing--return */ return; case 0x68: /* 0xc068 = STATEREG */ set_statereg(dcycs, val); return; case 0x69: /* 0xc069 */ /* just ignore, someone writing c068 with m=0 */ return; case 0x6a: /* 0xc06a */ case 0x6b: /* 0xc06b */ case 0x6c: /* 0xc06c */ case 0x6d: /* 0xc06d */ case 0x6e: /* 0xc06e */ case 0x6f: /* 0xc06f */ UNIMPL_WRITE; /* 0xc070 - 0xc07f */ case 0x70: /* 0xc070 = Trigger paddles */ paddle_trigger(dcycs); return; case 0x73: /* 0xc073 = multibank ram card bank addr? */ return; case 0x71: /* 0xc071 = another multibank ram card enable? */ case 0x7e: /* 0xc07e */ case 0x7f: /* 0xc07f */ return; case 0x72: /* 0xc072 */ case 0x74: /* 0xc074 */ case 0x75: /* 0xc075 */ case 0x76: /* 0xc076 */ case 0x77: /* 0xc077 */ case 0x78: /* 0xc078 */ case 0x79: /* 0xc079 */ case 0x7a: /* 0xc07a */ case 0x7b: /* 0xc07b */ case 0x7c: /* 0xc07c */ case 0x7d: /* 0xc07d */ UNIMPL_WRITE; /* 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: new_lcbank2 = ((loc >> 1) & 0x4) ^ 0x4; new_wrdefram = (loc & 1); if(new_wrdefram != g_c08x_wrdefram) { fixup_wrdefram(new_wrdefram); } switch(loc & 0xf) { case 0x1: /* 0xc081 */ case 0x2: /* 0xc082 */ case 0x5: /* 0xc085 */ case 0x6: /* 0xc086 */ case 0x9: /* 0xc089 */ case 0xa: /* 0xc08a */ case 0xd: /* 0xc08d */ case 0xe: /* 0xc08e */ /* Read rom, set lcbank2 */ set_statereg(dcycs, (g_c068_statereg & ~(0x04))| (new_lcbank2 | 0x08)); break; case 0x0: /* 0xc080 */ case 0x3: /* 0xc083 */ case 0x4: /* 0xc084 */ case 0x7: /* 0xc087 */ case 0x8: /* 0xc088 */ case 0xb: /* 0xc08b */ case 0xc: /* 0xc08c */ case 0xf: /* 0xc08f */ /* Read ram (clear RDROM), set lcbank2 */ set_statereg(dcycs, (g_c068_statereg & ~(0x0c))| (new_lcbank2)); break; } return; /* 0xc090 - 0xc09f */ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: UNIMPL_WRITE; /* 0xc0a0 - 0xc0af */ case 0xa0: case 0xa1: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: UNIMPL_WRITE; case 0xa2: /* Burger Times writes here on error */ case 0xa8: /* Kurzweil SMP writes to 0xc0a8, ignore it */ return; /* 0xc0b0 - 0xc0bf */ case 0xb0: /* Second sight stuff--ignore it */ return; case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: UNIMPL_WRITE; /* 0xc0c0 - 0xc0cf */ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: UNIMPL_WRITE; /* 0xc0d0 - 0xc0df */ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: UNIMPL_WRITE; /* 0xc0e0 - 0xc0ef */ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: write_iwm(loc, val, dcycs); return; /* 0xc0f0 - 0xc0ff */ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: UNIMPL_WRITE; default: printf("WRite loc: %x\n",loc); exit(-300); } break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* c1000 - c7ff */ UNIMPL_WRITE; case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: UNIMPL_WRITE; case 0xf: if((loc & 0xfff) == 0xfff) { /* cfff */ return; } UNIMPL_WRITE; } printf("Huh2? Write loc: %x\n", loc); exit(-290); } #if 0 int get_slow_mem(word32 loc, int duff_cycles) { int val; loc = loc & 0x1ffff; if((loc &0xf000) == 0xc000) { return(io_read(loc &0xfff, duff_cycles)); } if((loc & 0xf000) >= 0xd000) { if((loc & 0xf000) == 0xd000) { if(!LCBANK2) { /* Not LCBANK2 == be 0xc000 - 0xd000 */ loc = loc - 0x1000; } } } val = g_slow_memory_ptr[loc]; halt_printf("get_slow_mem: %06x = %02x\n", loc, val); return val; } int set_slow_mem(word32 loc, int val, int duff_cycles) { int or_pos; word32 or_val; loc = loc & 0x1ffff; if((loc & 0xf000) == 0xc000) { return(io_write(loc & 0xfff, val, duff_cycles)); } if((loc & 0xf000) == 0xd000) { if(!LCBANK2) { /* Not LCBANK2 == be 0xc000 - 0xd000 */ loc = loc - 0x1000; } } if(g_slow_memory_ptr[loc] != val) { or_pos = (loc >> SHIFT_PER_CHANGE) & 0x1f; or_val = DEP1(1, or_pos, 0); if((loc >> CHANGE_SHIFT) >= SLOW_MEM_CH_SIZE || loc < 0) { printf("loc: %08x!!\n", loc); exit(11); } slow_mem_changed[(loc & 0xffff) >> CHANGE_SHIFT] |= or_val; } /* doesn't shadow text/hires graphics properly! */ g_slow_memory_ptr[loc] = val; return val; } #endif /* IIgs vertical line counters */ /* 0x7d - 0x7f: in vbl, top of screen? */ /* 0x80 - 0xdf: not in vbl, drawing screen */ /* 0xe0 - 0xff: in vbl, bottom of screen */ /* Note: lines are then 0-0x60 effectively, for 192 lines */ /* vertical blanking engages on line 192, even if in super hires mode */ /* (Last 8 lines in SHR are drawn with vbl_active set */ word32 get_lines_since_vbl(double dcycs) { double dcycs_since_last_vbl; double dlines_since_vbl; double dcyc_line_start; word32 lines_since_vbl; int offset; dcycs_since_last_vbl = dcycs - g_last_vbl_dcycs; dlines_since_vbl = dcycs_since_last_vbl * (1.0 / 65.0); lines_since_vbl = (int)dlines_since_vbl; dcyc_line_start = (double)lines_since_vbl * 65.0; offset = ((int)(dcycs_since_last_vbl - dcyc_line_start)) & 0xff; lines_since_vbl = (lines_since_vbl << 8) + offset; if(lines_since_vbl < 0x10680) { return lines_since_vbl; } else { halt_printf("lines_since_vbl: %08x!\n", lines_since_vbl); printf("dc_s_l_v: %f, dcycs: %f, last_vbl_cycs: %f\n", dcycs_since_last_vbl, dcycs, g_last_vbl_dcycs); show_dtime_array(); show_all_events(); /* U_STACK_TRACE(); */ } return lines_since_vbl; } int in_vblank(double dcycs) { int lines_since_vbl; lines_since_vbl = get_lines_since_vbl(dcycs); if(lines_since_vbl >= 0xc000) { return 1; } return 0; } /* horizontal video counter goes from 0x00,0x40 - 0x7f, then 0x80,0xc0-0xff */ /* over 2*65 cycles. The last visible screen pos is 0x7f and 0xff */ /* This matches KEGS starting line 0 at the border for line -1 */ int read_vid_counters(int loc, double dcycs) { word32 mask; int lines_since_vbl; loc = loc & 0xf; lines_since_vbl = get_lines_since_vbl(dcycs); lines_since_vbl += 0x10000; if(lines_since_vbl >= 0x20000) { lines_since_vbl = lines_since_vbl - 0x20000 + 0xfa00; } if(lines_since_vbl > 0x1ffff) { halt_printf("lines_since_vbl: %04x, dcycs: %f, last_vbl: %f\n", lines_since_vbl, dcycs, g_last_vbl_dcycs); } if(loc == 0xe) { /* Vertical count */ return (lines_since_vbl >> 9) & 0xff; } mask = (lines_since_vbl >> 1) & 0x80; lines_since_vbl = (lines_since_vbl & 0xff); if(lines_since_vbl >= 0x01) { lines_since_vbl = (lines_since_vbl + 0x3f) & 0x7f; } return (mask | (lines_since_vbl & 0xff)); }