2021-07-07 15:00:47 +00:00
/*
* reinette , a french Apple II emulator , using SDL2
* and powered by puce65c02 - a WDS 65 c02 cpu emulator by the same author
* Last modified 1 st of July 2021
* Copyright ( c ) 2021 Arthur Ferreira ( arthur . ferreira2 @ gmail . com )
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
// code is not iso compliant : abuse of range expressions in switch statements
# include <stdio.h>
# include <stdlib.h>
# include "reinette.h"
//========================================== MEMORY MAPPED SOFT SWITCHES HANDLER
uint8_t Mmu : : softSwitches ( uint16_t address , uint8_t value , bool WRT ) {
2021-07-07 18:07:43 +00:00
static uint8_t dLatch = 0 ; // disk ][ I/O register
switch ( address ) {
// MEMORY MANAGEMENT (and KEYBOARD)
case 0xC000 : if ( WRT ) STORE80 = false ; else return KBD ; break ; // cause PAGE2 on to select AUX -- KEYBOARD return key code - if hi-bit is set the key code (7 lo-bits) is valid
case 0xC001 : if ( WRT ) STORE80 = true ; break ; // allow PAGE2 to switch MAIN / AUX
case 0xC002 : if ( WRT ) RAMRD = false ; break ; // read from MAIN
case 0xC003 : if ( WRT ) RAMRD = true ; break ; // read from AUX
case 0xC004 : if ( WRT ) RAMWRT = false ; break ; // write to MAIN
case 0xC005 : if ( WRT ) RAMWRT = true ; break ; // write to AUX
case 0xC006 : if ( WRT ) INTCXROM = false ; break ; // set peripheral roms for peripherals ($C100-$CFFF)
case 0xC007 : if ( WRT ) INTCXROM = true ; break ; // set internal rom for peripherals ($C100-$CFFF)
case 0xC008 : if ( WRT ) ALTZP = false ; break ; // MAIN stack & rero page
case 0xC009 : if ( WRT ) ALTZP = true ; break ; // AUX stack & rero page
case 0xC00A : if ( WRT ) SLOTC3ROM = false ; break ; // ROM in Slot 3
case 0xC00B : if ( WRT ) SLOTC3ROM = true ; break ; // ROM in AUX Slot
case 0xC00C : if ( WRT ) COL80 = false ; break ; // 80 COL OFF -> 40 COL
case 0xC00D : if ( WRT ) COL80 = true ; break ; // 80 COL ON
case 0xC00E : if ( WRT ) ALTCHARSET = false ; break ; // primary character set
case 0xC00F : if ( WRT ) ALTCHARSET = true ; break ; // alternate character set
case 0xC010 : KBD & = 0x7F ; return KBD ; // KBDSTROBE, clear hi-bit and return key code
// SOFT SWITCH STATUS FLAGS
case 0xC011 : return ( 0x80 * LCBK2 ) ;
case 0xC012 : return ( 0x80 * LCRD ) ;
case 0xC013 : return ( 0x80 * RAMRD ) ; // 0x80 if reads from AUX
case 0xC014 : return ( 0x80 * RAMWRT ) ; // 0x80 if writes from AUX
case 0xC015 : return ( 0x80 * INTCXROM ) ;
case 0xC016 : return ( 0x80 * ALTZP ) ; // 0x80 if using stack and zero page from AUX
case 0xC017 : return ( 0x80 * SLOTC3ROM ) ;
case 0xC018 : return ( 0x80 * STORE80 ) ; // do we store 80 col page 2 on MAIN or AUX
case 0xC019 : return ( 0x80 * VERTBLANK ) ;
case 0xC01A : return ( 0x80 * TEXT ) ; // read text switch
case 0xC01B : return ( 0x80 * MIXED ) ; // read mixed switch
case 0xC01C : return ( 0x80 * PAGE2 ) ; // read page 2 switch
case 0xC01D : return ( 0x80 * HIRES ) ; // read HiRes switch
case 0xC01E : return ( 0x80 * ALTCHARSET ) ; // alternate character set ?
case 0xC01F : return ( 0x80 * COL80 ) ; // 80 columns on ?
// SOUND
case 0xC020 : // TAPEOUT (shall we listen it ? - try SAVE from applesoft)
case 0xC030 : // SPEAKER
case 0xC033 : speaker - > play ( ) ; break ; // apple invader uses $C033 to output sound !
// GAME I/O STROBE OUT
case 0xC040 : break ;
// VIDEO MODES
case 0xC050 : TEXT = false ; video - > clearCache ( ) ; break ; // set Graphics
case 0xC051 : TEXT = true ; video - > clearCache ( ) ; break ; // set Text
case 0xC052 : MIXED = false ; video - > clearCache ( ) ; break ; // set Mixed to off
case 0xC053 : MIXED = true ; video - > clearCache ( ) ; break ; // set Mixed to on
case 0xC054 : PAGE2 = false ; video - > clearCache ( ) ; break ; // select page 1
case 0xC055 : PAGE2 = true ; video - > clearCache ( ) ; break ; // select page 2
case 0xC056 : HIRES = false ; video - > clearCache ( ) ; break ; // set HiRes to off
case 0xC057 : HIRES = true ; video - > clearCache ( ) ; break ; // set HiRes to on
// ANNUNCIATORS
case 0xC058 : if ( ! IOUDIS ) AN0 = false ; break ; // If IOUDIS off: Annunciator 0 Off
case 0xC059 : if ( ! IOUDIS ) AN0 = true ; break ; // If IOUDIS off: Annunciator 0 On
case 0xC05A : if ( ! IOUDIS ) AN1 = false ; break ; // If IOUDIS off: Annunciator 1 Off
case 0xC05B : if ( ! IOUDIS ) AN1 = true ; break ; // If IOUDIS off: Annunciator 1 On
case 0xC05C : if ( ! IOUDIS ) AN2 = false ; break ; // If IOUDIS off: Annunciator 2 Off
case 0xC05D : if ( ! IOUDIS ) AN2 = true ; break ; // If IOUDIS off: Annunciator 2 On
case 0xC05E : if ( ! IOUDIS ) AN3 = false ; DHIRES = true ; break ; // If IOUDIS off: Annunciator 3 Off
case 0xC05F : if ( ! IOUDIS ) AN3 = true ; DHIRES = false ; break ; // If IOUDIS off: Annunciator 2 On
// TAPE
case 0xC060 : break ; // TAPE IN
// PADDLES
case 0xC061 : return paddles - > PB0 ; // Push Button 0 / Open Apple
case 0xC062 : return paddles - > PB1 ; // Push Button 1 / Solid Apple
case 0xC063 : return paddles - > PB2 ; // Push Button 2 / Shift
case 0xC064 : return paddles - > read ( 0 ) ; // Paddle 0
case 0xC065 : return paddles - > read ( 1 ) ; // Paddle 1
case 0xC066 : return paddles - > read ( 2 ) ; // Paddle 2
case 0xC067 : return paddles - > read ( 3 ) ; // Paddle 3
case 0xC070 : paddles - > reset ( ) ; break ; // paddles timer reset
// IOUDIS
case 0xC07E : if ( WRT ) IOUDIS = false ; else return ( 0x80 * IOUDIS ) ; break ;
case 0xC07F : if ( WRT ) IOUDIS = true ; else return ( 0x80 * DHIRES ) ; break ;
// LANGUAGE CARD (used with MAIN and AUX)
2021-07-07 15:00:47 +00:00
case 0xC080 :
2021-07-07 18:07:43 +00:00
case 0xC084 : LCBK2 = 1 ; LCRD = 1 ; LCWR = 0 ; LCWFF = 0 ; break ; // LC2RD
case 0xC081 :
case 0xC085 : LCBK2 = 1 ; LCRD = 0 ; LCWR | = LCWFF ; LCWFF = ! WRT ; break ; // LC2WR
case 0xC082 :
case 0xC086 : LCBK2 = 1 ; LCRD = 0 ; LCWR = 0 ; LCWFF = 0 ; break ; // ROMONLY2
case 0xC083 :
case 0xC087 : LCBK2 = 1 ; LCRD = 1 ; LCWR | = LCWFF ; LCWFF = ! WRT ; break ; // LC2RW
case 0xC088 :
case 0xC08C : LCBK2 = 0 ; LCRD = 1 ; LCWR = 0 ; LCWFF = 0 ; break ; // LC1RD
case 0xC089 :
case 0xC08D : LCBK2 = 0 ; LCRD = 0 ; LCWR | = LCWFF ; LCWFF = ! WRT ; break ; // LC1WR
case 0xC08A :
case 0xC08E : LCBK2 = 0 ; LCRD = 0 ; LCWR = 0 ; LCWFF = 0 ; break ; // ROMONLY1
case 0xC08B :
case 0xC08F : LCBK2 = 0 ; LCRD = 1 ; LCWR | = LCWFF ; LCWFF = ! WRT ; break ; // LC1RW
// SLOT 1
case 0xC090 . . . 0xC09F : break ;
// SLOT 2
case 0xC0A0 . . . 0xC0AF : break ;
// SLOT 3
case 0xC0B0 . . . 0xC0BF : break ;
// SLOT 4
case 0xC0C0 . . . 0xC0CF : break ;
// SLOT 5
case 0xC0D0 . . . 0xC0DF : break ;
// SLOT 6 DISK ][
2021-07-07 15:00:47 +00:00
case 0xC0E0 . . . 0xC0E7 : disk - > stepMotor ( address ) ; break ; // MOVE DRIVE HEAD
2021-07-07 18:07:43 +00:00
case 0xC0E8 : disk - > unit [ disk - > curDrv ] . motorOn = false ; break ; // MOTOROFF
case 0xC0E9 : disk - > unit [ disk - > curDrv ] . motorOn = true ; break ; // MOTORON
case 0xC0EA : disk - > setDrv ( 0 ) ; break ; // DRIVE0EN
case 0xC0EB : disk - > setDrv ( 1 ) ; break ; // DRIVE1EN
case 0xC0EC : // Shift Data Latch
if ( disk - > unit [ disk - > curDrv ] . writeMode ) // writting
disk - > unit [ disk - > curDrv ] . data [ disk - > unit [ disk - > curDrv ] . track * 0x1A00 + disk - > unit [ disk - > curDrv ] . nibble ] = dLatch ; // good luck gcc
else // reading
dLatch = disk - > unit [ disk - > curDrv ] . data [ disk - > unit [ disk - > curDrv ] . track * 0x1A00 + disk - > unit [ disk - > curDrv ] . nibble ] ; // easy peasy
disk - > unit [ disk - > curDrv ] . nibble = ( disk - > unit [ disk - > curDrv ] . nibble + 1 ) % 0x1A00 ; // turn floppy of 1 nibble
return dLatch ;
case 0xC0ED : dLatch = value ; break ; // Load Data Latch
case 0xC0EE : // latch for READ
disk - > unit [ disk - > curDrv ] . writeMode = false ;
return disk - > unit [ disk - > curDrv ] . readOnly ? 0x80 : 0 ; // check protection
case 0xC0EF : disk - > unit [ disk - > curDrv ] . writeMode = true ; break ; // latch for WRITE
// SLOT 7
case 0xC0F0 . . . 0xC0FF : break ;
}
return cpu - > ticks % 256 ; // catch all, gives a floating value
2021-07-07 15:00:47 +00:00
}
//================================================================== MEMORY READ
uint8_t Mmu : : readMem ( uint16_t address ) {
2021-07-07 18:07:43 +00:00
switch ( address ) {
case 0x0000 . . . 0x01FF : // STACK and Zero Page in AUX or MAIN
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x0200 . . . 0x03FF : // MAIN or AUX
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x0400 . . . 0x07FF : // TEXT PAGE 1 in AUX or MAIN
if ( STORE80 ) {
if ( PAGE2 ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
}
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x0800 . . . 0x0BFF : // TEXT PAGE 2 in AUX or MAIN
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x0C00 . . . 0x1FFF : // AUX or MAIN
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x2000 . . . 0x3FFF : // HIRES PAGE 1
if ( STORE80 ) {
if ( PAGE2 & & HIRES ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
}
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x4000 . . . 0x5FFF : // HIRES PAGE 2 in AUX or MAIN
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0x6000 . . . 0xBFFF : // AUX or MAIN
if ( RAMRD ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return aux [ address ] ;
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ram [ address ] ;
break ;
case 0xC000 . . . 0xC0FF : // SOFT SWITCHES
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return softSwitches ( address , 0 , false ) ;
break ;
2021-07-07 15:00:47 +00:00
case 0xC100 . . . 0xC1FF : // SLOT 1 ROM or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM ) {
return rom [ address - ROMSTART ] ;
}
return sl1 [ address - SL1START ] ;
break ;
case 0xC200 . . . 0xC2FF : // SLOT 2 ROM or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM ) {
return rom [ address - ROMSTART ] ;
}
return sl2 [ address - SL2START ] ;
break ;
case 0xC300 . . . 0xC3FF : // SLOT 3 ROM or ROM : video
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM | | ! SLOTC3ROM ) {
return rom [ address - ROMSTART ] ;
}
return sl3 [ address - SL3START ] ;
break ;
case 0xC400 . . . 0xC4FF : // SLOT 4 ROM or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM ) {
return rom [ address - ROMSTART ] ;
}
return sl4 [ address - SL4START ] ;
break ;
case 0xC500 . . . 0xC5FF : // SLOT 5 ROM or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM ) {
return rom [ address - ROMSTART ] ;
}
return sl5 [ address - SL5START ] ;
break ;
2021-07-07 18:07:43 +00:00
case 0xC600 . . . 0xC6FF : // SLOT 6 ROM : DISK ][ or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM ) {
return rom [ address - ROMSTART ] ;
}
return sl6 [ address - SL6START ] ;
break ;
case 0xC700 . . . 0xC7FF : // SLOT 7 ROM or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM ) {
return rom [ address - ROMSTART ] ;
}
return sl7 [ address - SL7START ] ;
break ;
case 0xC800 . . . 0xCFFE : // SHARED EXANSION SLOTS ROM AREA or ROM
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
if ( INTCXROM | | ! SLOTC3ROM ) {
return rom [ address - ROMSTART ] ;
}
return slrom [ ( address & 0x0F00 ) > > 2 & 0xF ] [ address - SLROMSTART ] ;
break ;
case 0xCFFF : // turn off all slots expansion ROMs - TODO : NEEDS REWORK
disk - > unit [ disk - > curDrv ] . motorOn = false ;
return 0 ;
break ;
case 0xD000 . . . 0xDFFF : // ROM, MAIN-BK1, RAM-BK2, AUX-BK1 or AUX-BK2
if ( LCRD ) {
if ( LCBK2 ) {
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return auxbk2 [ address - BK2START ] ; // AUX Bank 2
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return rambk2 [ address - BK2START ] ; // MAIN Bank 2
}
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return auxlgc [ address - LGCSTART ] ; // AUX Bank 1
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ramlgc [ address - LGCSTART ] ; // MAIN Bank 1
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return rom [ address - ROMSTART ] ; // ROM
break ;
case 0xE000 . . . 0xFFFF : // ROM, MAIN-BK1 or AUX-BK1
if ( LCRD ) {
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF00FF00 ;
return auxlgc [ address - LGCSTART ] ; // AUX Bank 1
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return ramlgc [ address - LGCSTART ] ; // MAIN Bank 1
}
video - > ramHeatmap [ address ] | = 0xFF00FF00 ;
return rom [ address - ROMSTART ] ; // ROM
break ;
}
return cpu - > ticks % 256 ; // returns a floating value
2021-07-07 15:00:47 +00:00
}
//================================================================= MEMORY WRITE
void Mmu : : writeMem ( uint16_t address , uint8_t value ) {
2021-07-07 18:07:43 +00:00
switch ( address ) {
case 0x0000 . . . 0x01FF : // STACK and Zero Page in AUX or MAIN
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x0200 . . . 0x03FF : // MAIN or AUX
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x0400 . . . 0x07FF : // TEXT PAGE 1 in AUX or MAIN
if ( STORE80 ) {
if ( PAGE2 ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
}
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x0800 . . . 0x0BFF : // TEXT PAGE 2 in AUX or MAIN
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x0C00 . . . 0x1FFF : // MAIN or AUX
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x2000 . . . 0x3FFF : // HIRES PAGE 1
if ( STORE80 ) {
if ( PAGE2 & & HIRES ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
}
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x4000 . . . 0x5FFF : // HIRES PAGE 2 in AUX or MAIN
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0x6000 . . . 0xBFFF : // AUX or MAIN
if ( RAMWRT ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
aux [ address ] = value ;
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ram [ address ] = value ;
return ;
break ;
case 0xC000 . . . 0xC0FF : // softSwitches
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
softSwitches ( address , 0 , true ) ;
return ;
break ;
case 0xC100 . . . 0xCFFE : // readonly area
return ;
break ;
case 0xCFFF : // turn off all slots expansion ROMs - NEEDS REWORK soft switch ?
disk - > unit [ disk - > curDrv ] . motorOn = false ;
return ;
break ;
case 0xD000 . . . 0xDFFF : // ROM, MAIN-BK1, RAM-BK2, AUX-BK1 or AUX-BK2
if ( LCWR ) {
if ( LCBK2 ) {
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
auxbk2 [ address - BK2START ] = value ; // AUX Bank 2
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
rambk2 [ address - BK2START ] = value ; // MAIN Bank 2
return ;
}
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
auxlgc [ address - LGCSTART ] = value ; // AUX Bank 1
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ramlgc [ address - LGCSTART ] = value ; // MAIN Bank 1
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
return ;
break ;
case 0xE000 . . . 0xFFFF : // ROM, MAIN-BK1 or AUX-BK1
if ( LCWR ) {
if ( ALTZP ) {
video - > auxHeatmap [ address ] | = 0xFF0000FF ;
auxlgc [ address - LGCSTART ] = value ; // AUX Bank 1
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
ramlgc [ address - LGCSTART ] = value ; // MAIN Bank 1
return ;
}
video - > ramHeatmap [ address ] | = 0xFF0000FF ;
return ;
break ;
}
2021-07-07 15:00:47 +00:00
}
Mmu : : Mmu ( ) {
2021-07-07 18:07:43 +00:00
// TODO : give user the choice of the rom version
2021-07-07 15:00:47 +00:00
// pick one ROM file
2021-07-07 18:07:43 +00:00
// FILE* f = fopen("rom/appleII.rom", "rb"); // load the Apple II ROM
// FILE* f = fopen("rom/appleII+.rom", "rb"); // load the Apple II+ ROM
// FILE* f = fopen("rom/appleIIe.rom", "rb"); // load the Apple IIe ROM
FILE * f = fopen ( " rom/appleIIee.rom " , " rb " ) ; // load the Apple IIee ROM
2021-07-07 15:00:47 +00:00
fread ( rom , 1 , ROMSIZE , f ) ;
fclose ( f ) ;
// load DISK][ PROM
f = fopen ( " rom/diskII.rom " , " rb " ) ; // load the P5A disk ][ PROM
fread ( sl6 , 1 , 256 , f ) ;
fclose ( f ) ;
2021-07-07 18:07:43 +00:00
init ( ) ;
2021-07-07 15:00:47 +00:00
}
Mmu : : ~ Mmu ( ) {
2021-07-07 18:07:43 +00:00
// release the memory arrays ?
2021-07-07 15:00:47 +00:00
}
void Mmu : : init ( ) {
2021-07-07 18:07:43 +00:00
KBD = 0 ; // $C000, $C010 ascii value of keyboard input
PAGE2 = false ; // $C054 PAGE1 / $C055 PAGE2
TEXT = true ; // $C050 CLRTEXT / $C051 SETTEXT
MIXED = false ; // $C052 CLRMIXED / $C053 SETMIXED
HIRES = false ; // $C056 GR / $C057 HGR
DHIRES = false ; // 0xC05E / 0xC05F DOUBLE HIRES
COL80 = false ; // 80 COLUMNS
ALTCHARSET = false ;
LCWR = true ; // Language Card writable
LCRD = false ; // Language Card readable
LCBK2 = true ; // Language Card bank 2 enabled
LCWFF = false ; // Language Card pre-write flip flop
AN0 = false ;
AN1 = false ;
AN2 = true ;
AN3 = true ;
RAMRD = false ;
RAMWRT = false ;
ALTZP = false ;
STORE80 = false ;
INTCXROM = false ; // use slots roms
SLOTC3ROM = false ; // use AUX Slot rom
IOUDIS = false ;
VERTBLANK = true ;
memset ( ram , 0 , sizeof ( ram ) ) ; // 48K of MAIN in $000-$BFFF
memset ( aux , 0 , sizeof ( aux ) ) ; // 48K of AUX memory
memset ( ramlgc , 0 , sizeof ( ramlgc ) ) ; // MAIN Language Card 12K in $D000-$FFFF
memset ( rambk2 , 0 , sizeof ( rambk2 ) ) ; // MAIN bank 2 of Language Card 4K in $D000-$DFFF
memset ( auxlgc , 0 , sizeof ( auxlgc ) ) ; // AUX Language Card 12K in $D000-$FFFF
memset ( auxbk2 , 0 , sizeof ( auxbk2 ) ) ; // AUX bank 2 of Language Card 4K in $D000-$DFFF
// dirty hacks - fix when I know why
2021-07-07 15:00:47 +00:00
ram [ 0x4D ] = 0xAA ; // Joust won't work if this memory location equals zero
2021-07-07 18:07:43 +00:00
ram [ 0xD0 ] = 0xAA ; // Planetoids won't work if this memory location equals zero
2021-07-07 15:00:47 +00:00
}