diff --git a/CONFIG.md b/CONFIG.md index b1bee070..ffef262c 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -103,6 +103,12 @@ Adds support for the IEEC bus - for serial printers, disk drives, etc. Needs over 1000 bytes in KERNAL segment. If unsure - enable. +### `CONFIG_TAPE_TURBO` + +Adds a minimal turbo tape support - just LOAD command (device 7, like on _Action Replay_ and _Final_ cartridges) + +Needs about 350 bytes in KERNAL segment. If unsure - enable. + ## Multiple SID support The SID is a sound chip - original machine had one installed. However, mods exists to add more of them for improved sound capabilitiee. Emulators and FPGA machines typically allow to simulate more than one too. Unfortunately, there is no standard regarding how these additional chips are visible in the processor address space, and there is no sane way to detect it - thus, it has to be configurable. @@ -113,7 +119,7 @@ The SID support in the ROM is very limited - it only disables the sound during s Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively. -Each of these options needs 8 bytes in KERNAL segment. +Each of these options needs 3 bytes in KERNAL segment. ### `CONFIG_SID_D4XX` and `CONFIG_SID_D5XX` @@ -181,7 +187,7 @@ Needs 25 bytes more space in KERNAL segment for the code. In addition, each conf ### `CONFIG_EDIT_STOPQUOTE` -If enabled, STOP key terminates insert/quote mode (like on BlackBox cartridge). +If enabled, STOP key terminates insert/quote mode (like on some _Black Box_ cartridges). Feature needs 12 bytes in KERNAL segment. If unsure - enable. diff --git a/STATUS.md b/STATUS.md index 7eb547c7..0c59df05 100644 --- a/STATUS.md +++ b/STATUS.md @@ -20,6 +20,10 @@ NOTE: extra features and their syntax can change in the future! # Features missing +The following ROM features are currently missing and are not planned due to space considerations: + +* full tape support - VERIFY, SAVE, sequential files; tape is considered a legacy medium, so it's support is going to be limited +* mock 6551 emulation - this inly slows down the RS-232 support for original ROMs, probably noone needs it The following ROM features are currently missing: @@ -27,7 +31,8 @@ The following ROM features are currently missing: * BASIC variables * BASIC expression parsing * floating point routines -* tape support +* tape (normal mode) support +* IEC support for SAVE * RS-232 support * NMI handling is incomplete @@ -104,8 +109,8 @@ NOTE: Even the 'DONE' routines won't support features described as missing in on | :-------: | :--------: | :---------- | :------: | :--------------------------------------------------: | | `($028F)` | | `KEYLOG` | DONE | | | `$FF81` | `$FF5B` | `CINT` | DONE | | -| `$FF84` | `$FDA3` | `IOINIT` | PARTIAL | CIA initialization might be incomplete | -| `$FF87` | `$FD50` | `RAMTAS` | PARTIAL | probably shouldn't touch VIC and CIA's | +| `$FF84` | `$FDA3` | `IOINIT` | PARTIAL | CIA initialization incomplete | +| `$FF87` | `$FD50` | `RAMTAS` | DONE | | | `$FF8A` | `$FD15` | `RESTOR` | DONE | | | `$FF8D` | `$FD1A` | `VECTOR` | DONE | | | `$FF90` | | `SETMSG` | DONE | | diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s index 6e208cbf..e997bf79 100644 --- a/c64/,,config_generic.s +++ b/c64/,,config_generic.s @@ -43,7 +43,7 @@ #define CONFIG_IEC // #define CONFIG_IEC_JIFFYDOS // please keep disabled for now // #define CONFIG_TAPE_NORMAL // please keep disabled for now -// #define CONFIG_TAPE_TURBO // please keep disabled for now +#define CONFIG_TAPE_TURBO // #define CONFIG_RS232_UP2400 // please keep disabled for now // #define CONFIG_RS232_UP9600 // please keep disabled for now diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s index e416562c..220d86f7 100644 --- a/c64/,,config_mega65.s +++ b/c64/,,config_mega65.s @@ -45,7 +45,7 @@ #define CONFIG_IEC // #define CONFIG_IEC_JIFFYDOS // please keep disabled for now // #define CONFIG_TAPE_NORMAL // please keep disabled for now -// #define CONFIG_TAPE_TURBO // please keep disabled for now +#define CONFIG_TAPE_TURBO // #define CONFIG_RS232_UP2400 // please keep disabled for now // #define CONFIG_RS232_UP9600 // please keep disabled for now diff --git a/c64/,,config_testing.s b/c64/,,config_testing.s index 92e982eb..d0550369 100644 --- a/c64/,,config_testing.s +++ b/c64/,,config_testing.s @@ -44,7 +44,7 @@ #define CONFIG_IEC // #define CONFIG_IEC_JIFFYDOS // please keep disabled for now // #define CONFIG_TAPE_NORMAL // please keep disabled for now -// #define CONFIG_TAPE_TURBO // please keep disabled for now +#define CONFIG_TAPE_TURBO // #define CONFIG_RS232_UP2400 // please keep disabled for now // #define CONFIG_RS232_UP9600 // please keep disabled for now diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s index 2b80c95e..db0e9eeb 100644 --- a/c64/,,config_ultimate64.s +++ b/c64/,,config_ultimate64.s @@ -43,7 +43,7 @@ #define CONFIG_IEC // #define CONFIG_IEC_JIFFYDOS // please keep disabled for now // #define CONFIG_TAPE_NORMAL // please keep disabled for now -// #define CONFIG_TAPE_TURBO // please keep disabled for now +#define CONFIG_TAPE_TURBO // #define CONFIG_RS232_UP2400 // please keep disabled for now // #define CONFIG_RS232_UP9600 // please keep disabled for now diff --git a/c64/aliases/,aliases_config.s b/c64/aliases/,aliases_config.s index 2725bc9e..dbc3a540 100644 --- a/c64/aliases/,aliases_config.s +++ b/c64/aliases/,aliases_config.s @@ -299,8 +299,6 @@ .eval features_str = ADD_FEATURE(features_str, "TAPE NORMAL+TURBO") #endif - .eval feature_new_line = true - #if CONFIG_IEC .eval features_str = ADD_FEATURE(features_str, "IEC") #endif diff --git a/c64/kernal/init/fce2.hw_entry_reset.s b/c64/kernal/init/fce2.hw_entry_reset.s index 14014a02..29348a67 100644 --- a/c64/kernal/init/fce2.hw_entry_reset.s +++ b/c64/kernal/init/fce2.hw_entry_reset.s @@ -10,12 +10,9 @@ hw_entry_reset: sei // disable the interrupts, as fast as possible - they are disabled in case of HW reset, // but this routine can be also called manually - ldx #$00 - sta VIC_SCROLX // turn the display off - we want as little screen artifacts as possible - cld // required for all CPUs - due to possibility of manual call - dex // $FF - to initialize stack pointer + ldx #$FF txs // The following routine is based on reading the public KERNAL jumptable routine @@ -28,6 +25,10 @@ hw_entry_reset: bne !+ jmp (ICART_COLD_START) !: + // Disable the screen (and set 40 columns) to prevent visual glitches later + ldx #$28 + stx VIC_SCROLX + // Initialising IO is obviously required. Also indicated by c64 prg p269. jsr JIOINIT diff --git a/c64/kernal/init/fd50.ramtas.jmp.s b/c64/kernal/init/fd50.ramtas.jmp.s deleted file mode 100644 index b20ed77e..00000000 --- a/c64/kernal/init/fd50.ramtas.jmp.s +++ /dev/null @@ -1,6 +0,0 @@ - -// Our implementation is longer than the original one, -// placing it here would cause a collision with OPEN - -RAMTAS: - jmp ramtas_real diff --git a/c64/kernal/init/ramtas_real.s b/c64/kernal/init/fd50.ramtas.s similarity index 55% rename from c64/kernal/init/ramtas_real.s rename to c64/kernal/init/fd50.ramtas.s index 3838b2d2..70cb41c7 100644 --- a/c64/kernal/init/ramtas_real.s +++ b/c64/kernal/init/fd50.ramtas.s @@ -8,52 +8,33 @@ // CPU registers that has to be preserved (see [RG64]): none // -ramtas_real: +RAMTAS: + // C64 Programmer's Reference guide p291: // Clear $0000-$0101, $0200-$03ff // PGS: $0000, $0001 are CPU IO ports, so shouldn't get written to - ldy #$02 - lda #$00 -!: - sta $00,y - iny - bne !- -!: // How many ways are there to efficiently erase these two pages // of RAM? We would like to avoid any unnecessary byte similarity // with the C64 KERNAL. Thus we do $0300 before $0200, even though // with the longer sequence of identicale bytes we see no basis for // it being copyrightable. Again, we just want to redue the attack // surface for any misguided suit. + + ldy #$00 + lda #$00 +!: sta $0300,Y sta $0200,Y + sta $0002,Y // that's why we don't use .X for index, we do not want zeropage addressing here! iny bne !- // Allocate cassette buffer - // "Mapping the C64", p237 - lda #<$033C - sta TAPE1+0 - lda #>$033C - sta TAPE1+1 - - // set screen address to $0400 - // https://www.c64-wiki.com/wiki/Screen_RAM - // Since we are setting $D018, we also make sure we are using the - // ROM character set (C64 Programmer's Reference Guide p322) - lda #$14 - sta VIC_YMCSB - - // Make sure we have the correct VIC-II memory bank for the screen to really be at $0400 - // and not $4400, $8400 or $C400 - // https://www.c64-wiki.com/wiki/VIC_bank#Selecting_VIC_banks - lda CIA2_DDRA - ora #$03 - sta CIA2_DDRA - lda CIA2_PRA - ora #$03 - sta CIA2_PRA + ldx #<$033C + stx TAPE1+0 + ldx #>$033C + stx TAPE1+1 // Set screen address pointer ("Compute's Mapping the 64" p238) // This is obvious boiler plate containing no creative input, but to avoid @@ -62,30 +43,41 @@ ramtas_real: ldx #>$0400 stx HIBASE - // Work out RAM size and put in MEMSTR and MEMSIZK - // "Compute's Mapping the 64", p54 - // http://unusedino.de/ec64/technical/project64/mapping_c64.html + // Set BASIC start text pointer + // (remember, that low memory is 0 initialized at this moment) + ldx #>$0800 stx MEMSTR+1 - ldx #$00 - stx MEMSTR+0 - stx MEMSIZK+0 + + // Work out RAM size and put in MEMSIZK // Try to modify $8000, if it fails then RAM ends at $7FFF, else $9FFF + ldx $8000 inx stx $8000 cpx $8000 - bne ramtas_32K_RAM + bne ramtas_32k + + // FALLTROUGH + +ramtas_40k: + + // 40K RAM - restore memory content, set MEMSIZK + + ldy #$A0 +!: + sty MEMSIZK+1 + + // Always restore memory, cartridge might have RAM under ROM + dex stx $8000 - ldx #$A0 - stx MEMSIZK+1 - bne !+ // always non-zero, saves one byte -ramtas_32K_RAM: - dex - stx $8000 // case there is RAM under the ROM - ldx #$80 - stx MEMSIZK+1 -!: rts + +ramtas_32k: + + // 32K RAM - restore memory content, set MEMSIZK + + ldy #$80 + bne !- // branch always diff --git a/c64/kernal/init/fda3.ioinit.s b/c64/kernal/init/fda3.ioinit.s index 23687e37..59fa824d 100644 --- a/c64/kernal/init/fda3.ioinit.s +++ b/c64/kernal/init/fda3.ioinit.s @@ -11,39 +11,71 @@ IOINIT: - // Set $00/$01 port mode and value + // + // First initialize the CPU port, to make sure we have correct memory map + // + // We want BASIC and KERNAL ROMs mapped, and datasette motor off // (https://www.c64-wiki.com/wiki/Zeropage) // Work around for VICE bug: Writing $00 before $01 results in rubbish in $01 // after. https://sourceforge.net/p/vice-emu/bugs/1057/ - lda #$27 + ldx #$27 + stx CPU_R6510 ldx #$EF - sta CPU_R6510 stx CPU_D6510 // [CM64] page 4 - // Silence the SID chips, depending on the configuration + // + // Now prevent the CIAs from generating interrupts, who knows what damage they can do + // + + // Disable IRQ generation for both CIAs - see [CM64], page 149 + + ldx #$7F + stx CIA1_ICR // $DC0D + stx CIA2_ICR // $DD0D + + // See discussion here: + // https://www.lemon64.com/forum/viewtopic.php?t=41744&sid=e294c254db2ba671cde643f100aae341 + // It seems that initializing this register to $7F is the best idea - UDTIM key scanning + // also leaves this at $7F + + stx CIA1_PRA // $DC00 + + // + // Now silence the SID chip(s), depending on the configuration - we want them silent ASAP + // + + // First the standard chip (skip if it is covered by whole $D4XX range) + + lda #$00 #if !CONFIG_SID_D4XX - lda SID_SIGVOL - and #$F0 sta SID_SIGVOL #endif // !CONFIG_SID_D4XX + // Silence manually configured 2nd and 3rd SIDs + +#if CONFIG_SID_2ND + sta SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS +#endif // CONFIG_SID_2ND + +#if CONFIG_SID_3RD + sta SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS +#endif // CONFIG_SID_3RD + + // Silence whole D4XX and D5XX ranges (if configured) + #if CONFIG_SID_D4XX || CONFIG_SID_D5XX + ldy #$00 !: #if CONFIG_SID_D4XX - lda SID_SIGVOL, Y - and #$F0 - sta SID_SIGVOL, Y + sta SID_SIGVOL + $000, Y #endif // CONFIG_SID_D4XX #if CONFIG_SID_D5XX - // SIDs under $D5xx - lda SID_SIGVOL + $100, Y - and #$F0 sta SID_SIGVOL + $100, Y #endif // CONFIG_SID_D4XX @@ -52,50 +84,20 @@ IOINIT: adc #$20 tay bne !- + #endif // CONFIG_SID_D4XX || CONFIG_SID_D5XX -#if CONFIG_SID_2ND - lda SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS - and #$F0 - sta SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS -#endif // CONFIG_SID_2ND + // + // Now continue the CIAs initialization + // -#if CONFIG_SID_3RD - lda SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS - and #$F0 - sta SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS -#endif // CONFIG_SID_3RD - - // Initialize CIAs - - // XXX: calibrate TOD for both CIA's, see here: https://codebase64.org/doku.php?id=base:efficient_tod_initialisation - - // Enable CIA1 IRQ and ~50Hz timer (https://csdb.dk/forums/?roomid=11&topicid=69037) - - // First disable IRQ generation for both CIA's - lda #$7F - sta CIA2_ICR - sta CIA1_ICR - - // Enable timer interrupt - lda #$81 - sta CIA1_ICR - - // Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts) - lda #$11 - sta CIA1_CRA - lda CIA1_ICR - - // Setup the CIA1 for reading the keyboard - 'POKE 56322, 0' on original ROMs proves this - // is done during initialization, not during the interrupt + // For CIA #1 we need port A as output and port B as input to scan the keyboard ldx #$FF - stx CIA1_DDRA // output - inx // $00 - stx CIA1_DDRB // input - - // Value checked on original ROM - stx CIA2_DDRA + stx CIA1_DDRA // $DC02 + inx + stx CIA1_DDRB // $DC03 + stx CIA2_DDRB // $DD03 // XXX this port is used for RS-232, value here is most likely wrong! #if CONFIG_KEYBOARD_C65 || CONFIG_KEYBOARD_C65_CAPS_LOCK @@ -104,13 +106,38 @@ IOINIT: #endif - // Set DDR on CIA2 for IEC bus, VIC-II banking + // Set DDR on CIA2 for IEC bus, VIC-II banking (see [CM64], $DDOO description on page 193) lda #$3F - sta CIA2_DDRA + sta CIA2_DDRA // $DD02 - // Set VIC-II bank - needed at least for 'Operacja Proboszcz' game - lda #%00000011 - sta CIA2_PRA + // XXX detect TOD clock, see https://codebase64.org/doku.php?id=base:efficient_tod_initialisation + + // XXX how to initialize these timers??? + // stx CIA1_CRB // $DC0F + // stx CIA2_CRA // $DD0E + // stx CIA2_CRB // $DD0F + + // Set VIC-II bank - at least the 'Operacja Proboszcz' game needs this within IOINIT + // Checked on original ROMs, that it sets bit #2 (RS-232 output) high + + ldx #%00000111 // XXX adapt this to IEC idle state, JMP at the end won't be needed + stx CIA2_PRA // $DD00 + + // + + ldy #<16421 + ldx #>16421 + + sty CIA1_TIMALO // $DC04 + stx CIA1_TIMAHI // $DC05 + + // Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts) + ldx #$11 + stx CIA1_CRA // $DC0E + + // Enable timer interrupt + ldx #$81 + stx CIA1_ICR // $DC0D #if CONFIG_IEC diff --git a/c64/kernal/init/setup_pal_ntsc.s b/c64/kernal/init/setup_pal_ntsc.s index 0b5ae619..99668527 100644 --- a/c64/kernal/init/setup_pal_ntsc.s +++ b/c64/kernal/init/setup_pal_ntsc.s @@ -32,7 +32,7 @@ setup_pal: // ldx #>16380 // PAL C64 (https://codebase64.org/doku.php?id=base:cpu_clocking), - // is clocked at 0.985248 MHz, so that 1/60s is 16421 CPU cycles + // is clocked at 0.985248 MHz, so that 1/60s is 16421 ($4025) CPU cycles ldy #<16421 ldx #>16421 @@ -43,8 +43,8 @@ setup_pal: setup_pal_ntsc_end: - sty CIA1_TIMALO - stx CIA1_TIMAHI + sty CIA1_TIMALO // $DC04 + stx CIA1_TIMAHI // $DC05 sta TVSFLG @@ -55,7 +55,7 @@ setup_ntsc: // Set timer interval to ~1/60th of a second // NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking), - // is clocked at 1.022727 MHz, so that 1/60s is 17045 CPU cycles + // is clocked at 1.022727 MHz, so that 1/60s is 17045 ($4295) CPU cycles ldy #<17045 ldx #>17045 diff --git a/c64/kernal/tape/load_tape_turbo.s b/c64/kernal/tape/load_tape_turbo.s index 1e9fe9b9..bf1cb7e0 100644 --- a/c64/kernal/tape/load_tape_turbo.s +++ b/c64/kernal/tape/load_tape_turbo.s @@ -12,6 +12,8 @@ load_tape_turbo: + // XXX prepare SID, store screen color somewhere, read header + jsr tape_ditch_verify // only LOAD is supported, no VERIFY ldy #$00 @@ -91,16 +93,24 @@ tape_turbo_get_bit: lda #$10 !: - bit CIA2_ICR + bit CIA1_ICR beq !- // busy loop to detect signal lda CIA2_ICR pha lda #$19 sta CIA2_CRA pla - sta VIC_EXTCOL // use bitvalue as d020 effect (I love that one) - lsr + + pha // audio/video effects + asl + sta SID_SIGVOL + beq !+ + lda #$06 +!: + sta VIC_EXTCOL + pla + lsr rts diff --git a/c64/kernal/tape/tape_common.s b/c64/kernal/tape/tape_common.s index 935915aa..9e130f44 100644 --- a/c64/kernal/tape/tape_common.s +++ b/c64/kernal/tape/tape_common.s @@ -45,6 +45,8 @@ tape_ask_play: ldx #__MSG_KERNAL_PRESS_PLAY jsr print_kernal_message + // FALLTROUGH + tape_wait_button_loop: jsr udtim_keyboard @@ -71,7 +73,8 @@ tape_load_success: jsr screen_show jsr tape_motor_off - + + cli jmp lvs_success_end @@ -80,6 +83,7 @@ tape_load_error: jsr screen_show jsr tape_motor_off + cli jmp lvs_load_verify_error