Menu

#2145 Incorrect ROM/RAM Paging in VICE with COMAL80 CRT

v3.9
closed-fixed
gpz
Cartridges
2025-06-14
2025-06-12
ClausS
No

Description:
In the VICE emulator, a bug occurs when COMAL80 uses its internal CALL routine
to invoke a ROM-based routine from a RAM-based COMAL software package.

Background:
COMAL80 uses up to six switchable 16KB ROM banks. Paging is done by writing to $DE00.
Based on hardware design, the bit layout of $DE00 is as following in COMAL80:

  • D0–D2: bank selection (banks 1–6)
  • D6: disable ROM (expose RAM)
  • D3, D4, D5, D7: unused

To switch banks during execution, COMAL80 uses a RAM-based CALL routine:
JSR CALL
!by PAGE
!word ADDR

Bug Description:

  • Expected: CALL from RAM-based pages ($4x) works correctly.
  • Observed: In VICE, the jump works, but return fails → crash.
  • Using $E0 instead of $4x makes the CALL work in VICE.
  • Issue does NOT occur:
  • on real hardware
  • in other emulators like Denise

Technical Note:
Page ID $4x = %-1---xxx
High bits $4x = RAM indicator
Low bits x = page number

Steps to Reproduce:

  1. Run COMAL80 in VICE with original CRT.
  2. Load a RAM-based software package using CALL.
  3. Use CALL with page $4x → crash.
  4. Use CALL with $Ex instead → works fine.

Expected Result:
CALL should work and return to caller page ID $4x.

Actual Result:
VICE fails to return correctly from CALL, causing crashes.

Test Program:
A minimal test program demonstrates the issue:

  • Works on real C64
  • Works in Denise and CRT in KFF
  • Fails in VICE with $4x
  • Works in VICE with $Ex

Environment:

  • VICE version: 3.9
  • COMAL80: Original CRT
  • Other tested emulators: Denise, CRT Image in KFF

Conclusion:
VICE's $DE00 handling is not fully compatible with COMAL80 paging logic.
VICE must support valid COMAL80 page identifiers ($4x) for correct behavior.

Discussion

  • gpz

    gpz - 2025-06-12

    VICE uses this right now:

        bit 7   : exrom?
        bit 6   : game?
        bit 5   : unknown function (used by the software to disable the cartridge)
        bit 4   : unused?
        bit 3   : unused?
        bit 2   : selects user eprom (bank MSB)
        bit 0-1 : selects bank
    

    and implements the upper bits like this:

    case 0xe0: cmode = CMODE_RAM
    case 0x80: cmode = CMODE_16KGAME
    case 0x40: cmode = CMODE_8KGAME

    so yeah, the software uses them and they probably are used for something :)

    Also, "banks 1.-6" confuses me - it's not 8 banks? Perhaps that is the problem here, ie banking is not linear, but there is a "gap" we need to consider?

     
  • ClausS

    ClausS - 2025-06-13

    Thank you for your response.

    I would like to provide additional background and reasoning to support the conclusion that the current COMAL80 CRT file is likely based on a hardware variant that does not match the official Commodore cartridge and that this mismatch contributes to the issues observed in emulation (specifically in VICE).

    Context and Assumption
    It appears that the COMAL80 CRT was created using a hardware layout corresponding to a cartridge distributed by the Comal Users Group, U.S.A., Limited (Madison, Wisconsin), rather than the official Commodore version.

    Historical Overview

    1. Grey Cartridge (Comal Users Group, USA)
    2. Produced around 1984–1985, likely with UniComal Denmark’s approval.
    3. Approx. 2,000 units distributed (according to COMAL Today).
    4. Hardware Details:
    5. 4 sockets populated with 16 KB EPROMs (27128)
    6. Bits 0 and 1 select among the 4 EPROMs
    7. Bits 5 and 6 control EXROM and GAME
    8. No additional socket, but it was possible to piggyback a fifth EPROM via minor hardware mod

    9. Black Cartridge (Official Commodore Release)

    10. Used internationally and with a different hardware configuration:
    11. Two fixed 32 KB ROMs (Commodore) and one socket for a 32 KB (or with hardware modification 64 KB ) EPROM
    12. Bits 0 and 1 select between the 4×16 KB banks
    13. Bit 3 switches to the optional third socket
    14. Bit 6 simultaneously switches EXROM and GAME

    Software Behavior

    In the official COMAL80 v2.01 source (e.g. C64SYMB), the cartridge banks are switched using the following definitions:

    PAGE0 = %11100000 ; NO EXPANSION
    PAGE1 = %10000000 ; CARTRIDGE OVERLAY 1 ($8000-$BFFF)
    PAGE2 = %10000001 ; OVERLAY 2
    PAGE3 = %10000010 ; OVERLAY 3
    PAGE4 = %10000011 ; OVERLAY 4
    PAGE5 = %10000100 ; OVERLAY 5
    PAGE6 = %10000101 ; OVERLAY 6

    Notably, PAGE0 sets Bit 5 to 1, which does not match the behavior of the official Commodore black cartridge. However, because Bit 5 is not explicitly checked in the software, this does not cause issues on real hardware.

    The complete, but only very slightly documented Source-Code of COMAL80 2.01 can be found on my GitHub Page: https://github.com/LeshanDaFo/C64-COMAL-2.01

    However, it should be possible to switch up to 8 banks in the VICE emulation software, as this was used in the past by the PAKMA extension. And it doesn't interfere with the normal operation of the original software.

    Observed Issue

    In the VICE emulator, the actual software design leads to unexpected switching behavior or failure to correctly map cartridge banks, likely because VICE emulates the U.S. layout variant, not the official Commodore cartridge layout variant.

    Recommendation

    To ensure consistent emulator behavior and future compatibility, I recommend:

    • Aligning the CRT layout and logic with the official Commodore black cartridge, particularly regarding how EXROM/GAME and banks are switched
    • Alternatively, providing support for both cartridge variants, possibly through
    • a different CRT header variant
    • A clear note in the documentation identifying the intended hardware base

    Conclusion

    This issue appears to affect VICE emulation only — not real C64 hardware or other C64 emulation software. However, for long-term preservation and accurate emulation, it would be beneficial to adapt the CRT to reflect the widely recognized official Commodore design, or clearly mark it as being based on the U.S. variant.

    Attachments:
    – Schematics of both cartridge types can be found on my GitHub-Page:
    https://github.com/LeshanDaFo/C64-COMAL-2.01/blob/main/PCB-Layout/2.0%20Cartridge%20Black.pdf
    https://github.com/LeshanDaFo/C64-COMAL-2.01/blob/main/PCB-Layout/2.0%20Cartridge%20Gray.pdf

     
  • ClausS

    ClausS - 2025-06-13

    I have found a solution.
    Replacing the following code:

    static void comal80_io1_store(uint16_t addr, uint8_t value)
    {
        int cmode, currbank;
    
        currregval = value & 0xc7;
        currbank = value & 7;
    
        switch (value & 0xe0) {
            case 0xe0:
                cmode = CMODE_RAM;
                break;
            default:
            case 0x80:
                cmode = CMODE_16KGAME;
                break;
            case 0x40:
                cmode = CMODE_8KGAME;
                break;
        }
    #ifdef DEBUGCART
        if ((value != 0x82) && (value != 0x83)) {
            DBG(("COMAL80: IO1W %04x %02x mode: %d bank: %d\n", addr, value, cmode, currbank));
        }
    #endif
        cart_config_changed_slotmain(0, (uint8_t)(cmode | (currbank << CMODE_BANK_SHIFT)), CMODE_READ);
    }
    

    with this:

    static void comal80_io1_store(uint16_t addr, uint8_t value)
    {
        int cmode, currbank;
    
        currregval = value & 0xc7;
        currbank = value & 7;
    
        if (value & 0x40) {
            cmode = CMODE_RAM;
        } else {
            cmode = CMODE_16KGAME;
        }
    
    #ifdef DEBUGCART
        if ((value != 0x82) && (value != 0x83)) {
            DBG(("COMAL80: IO1W %04x %02x mode: %d bank: %d\n", addr, value, cmode, currbank));
        }
    #endif
        cart_config_changed_slotmain(0, (uint8_t)(cmode | (currbank << CMODE_BANK_SHIFT)), CMODE_READ);
    }
    

    will solve the problem.

     
  • gpz

    gpz - 2025-06-13

    Interesting info... I'll have a look at those layouts and see if we really need two variants

    Could you point to the exact cartridge image that you used to reproduce the problem?

     
    • ClausS

      ClausS - 2025-06-14

      Actually there are 2 different version existing of COMAL80 2.01
      the pictures of the start screen can be found on my GitHub page in the README.md
      And the two CRT files are also available there.

      1. Copyright (C) 1984 by UniComal ApS (grey module version)
      2. (C) 1984 by UniComal & Commodore (black module version)
       

      Last edit: ClausS 2025-06-14
  • gpz

    gpz - 2025-06-13

    Oh and the most important question here is: The software does (always) run on both of these cartridges? Or is there software that only works on one of those variants? In that case, i'd like to see at least one image of each (and a way to tell it "works") :)

     
    • ClausS

      ClausS - 2025-06-14

      For my understanding, the software should run on both versions. And with your fixes, it will.

       
  • gpz

    gpz - 2025-06-13

    (I was going to point you to the Comal80 efforts going on in F64 - then realized you were knee deep into it. lol!)

     
    • ClausS

      ClausS - 2025-06-14

      I probably have the best overview of Comal's internal processes, but maybe I'm wrong. lol

       
  • gpz

    gpz - 2025-06-13

    Steps to Reproduce:
    1. Run COMAL80 in VICE with original CRT.
    2. Load a RAM-based software package using CALL.
    3. Use CALL with page $4x → crash.
    4. Use CALL with $Ex instead → works fine.

    would you give me some instructions for dummys? ideally also a d64 with whatever i need to load? i have never used this thing :)

     
  • gpz

    gpz - 2025-06-13

    I fixed it all up locally (by default it behaves like "black", and there is a new hardware variant that behaves like "grey" - should we ever need that)

    As soon as you tell me how to test this i can commit :D

     
  • gpz

    gpz - 2025-06-13

    ah well, check r45698 - test it please :)

     
  • ClausS

    ClausS - 2025-06-14

    I get an error during compiling the code on my mac:
    /Volumes/Common/SourceForge/vice-emu-code/vice/src/arch/gtk3/joystickdrv/joystick_osx.c:327:64: fatal error: too many arguments to function call, expected 2, have 3
    327 | joy_axis_event(joyport, e.ordinal, JOY_AXIS_NEGATIVE);
    | ~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~
    /Volumes/Common/SourceForge/vice-emu-code/vice/src/joyport/joystick.h:408:6: note: 'joy_axis_event' declared here
    408 | void joy_axis_event (joystick_axis_t *axis, int32_t value);
    | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 error generated.
    make[5]: *** [joystick_osx.o] Error 1
    make[4]: *** [install-recursive] Error 1
    make[3]: *** [install-recursive] Error 1
    make[2]: *** [install-recursive] Error 1
    make[1]: *** [install] Error 2
    make: *** [install-recursive] Error 1

     
    • dqh

      dqh - 2025-06-14

      Will at least get it building again today.

       
      • ClausS

        ClausS - 2025-06-14

        Then I will try to compile it later.

         
  • gpz

    gpz - 2025-06-14

    gna yes, macOS is currently broken :( not sure if you can disable joystick support completely as a workaround...

     
  • ClausS

    ClausS - 2025-06-14

    I think to disable the joystick support is beyond my capabilities. :(

    But I have some good news.
    I managed to patch an older version with the changes you made.
    I'm able to compile this, and it works now as expected.

    Existing CRT images are now correctly recognized as the black CRT image.
    If you set bit $1A in the CRT image to $01, it will be recognized as the gray CRT module.

    I tested it with my test program and it now works as it should under both images.

    From my point of view this patch is ok

    Additional Info:

    As you may know, Comal80 can load so-called packages. These packages contain procedures and functions that can be used from a running program.

    Instructions on how these packages should be structured can be found in the book https://archive.org/details/comal-80-for-the-commodore-64 starting on page 255, or directly starting on page 261.

    There are also demo disks with the corresponding source code; one can be found on my GitHub page: https://github.com/LeshanDaFo/C64-COMAL-2.01/raw/main/C64-comal-80-demo-disk.d64

    My test program has a very simple structure:

    start   =   $8009
    
        !source "c64symb.asm"
    
    *= start
    
        !by  DEFPAG                     ; ram area from $8000
        !word endPkg                    ; the program end address
        !word DUMMY                     ; the address of the signal handler
                                        ; DUMMY points to a RTS
    ;-- package table -----------------
        !pet $04,"test"                 ; package name
        !word ptTest                    ; proc table
        !word init_Test                 ; proc init
        !by $00
    
    ;-- init --------------------------
    init_Test
    
    ;-- call a routine in another package
    
    inc $d020                           ; check if the init is called
    jsr CALL
    !by PAGE4
    !word $8d9a                         ; this points to a simple RTS in PAGE4
    inc $d021                           ; check if we come back
    RTS
    
    ;-- procedure table ---------------
        ptTest
    ; no procedure for this sample
        !by $00
    
    endPkg
    

    You can find a disk with a test program attched.

    How to use:

    1. attach any COMAL80 CRT to VICE
    2. attach the disk
    3. use cat to show the directory
    4. execute the following command: 'link test.seq'
    5. execute the command 'use test'

    with the old version of VICE, it will crash, but with the new version, it workd fine.

     
  • compyx

    compyx - 2025-06-14

    About MacOS joystick support: there is a patch that fixes the THEC64 joystick on MacOS and uses the updated API, fixing joystick support for MacOS in the process.

    However, I'm currently working on the joystick code in a branch, so to avoid any possible merge conflicts, applying that patch will need to happen after I've merged my work in the branch back into trunk.

    I don't have a timeline for when we can fix the MacOS joystick code: I'm working on polling joysticks from the UI (that works) but creating usable and non-messy dialogs and widgets for mappings and calibration is taking a bit more time than I thought :)

     
    • ClausS

      ClausS - 2025-06-14

      No Problem for me, take your time.
      I only have patched on older Version, to see, if the problem is solved now.
      And it seems it is. So far i did not get any error.

       
  • gpz

    gpz - 2025-06-14
    • status: open --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB