Menu

#115 [GBZ80] ROM Bank Support

None
open
gbz80 (1)
5
2020-07-22
2018-06-26
caller
No

I have been trying to get ROM Bank Support in SDCC working, but I fail to get it to work. I figured out that there is a problem when linking Objects, they are not properly placed in ROM, and when using makebin to convert the IHX output to a ROM Image, the Areas which define Banks are overlayed and overwritten by each other.
For example, the Gameboy requires mappable Banks to begin at 0x4000, and range up to 0x7FFF. Now if I wanted to have 1 fixed Bank mapped to 0x0000-0x3FFF, and 3 Banks each mapped to 0x4000-0x7FFF in order to get 64kBytes of ROM total, I pass the following parameters to the Linker

-Wl -b _bank_0=0x0000, -b _bank_1=0x4000, -b _bank_2=0x4000, -b _bank_3=0x4000 

My Banks are named accordingly bank_0 to bank_3. The Map file shows that each bank starts with the correct address, but when the ihx file is translated to bin with makebin, only the contents of the last Bank remain, because it apparently overwrites everything at the location.
Am I missing anything to get Bank mapping to work?

Thanks

Discussion

  • Maarten Brock

    Maarten Brock - 2018-10-14

    I'm not sure if this works with the GBZ80, but the idea with banks should be to place them like this:
    bank_0: 0x0000 - 0x3FFF (unbanked common area)
    bank_1: 0x14000 - 0x17FFF
    bank_2: 0x24000 - 0x27FFF
    bank_3: 0x34000 - 0x37FFF
    This way the compiler can use the lowest 16 bits as the physical address for the processor and the upper byte as the bank to select. You probably need to post-process the generated hex-file to map the banks to the ROM layout. For this srecord can be used.

     
    • Sebastian Riedel

      I agree that -b _bank_1=0x14000, -b _bank_2=0x24000, -b _bank_3=0x34000 should be used.
      I will see if I can teach makebin to handle those virtual addresses correctly, currently (4.0.0) it places them all at 0x4000.

       
  • Sebastian Riedel

    • labels: --> gbz80
    • assigned_to: Sebastian Riedel
    • Group: -->
     
  • Sebastian Riedel

    Workaround added in [r11749].
    I will see if I can get the address translation into the linker.

     
    • Tony Pavlov

      Tony Pavlov - 2020-07-21

      ihx (Intel Hex) file format describes the way, how the rom is written into the memory of the chip. many hardware programmer devices use those files directly. it is not obvious for a third-party manufacturer that he should write addresses 0x24000..0x27fff into 0x4000..0x7ffff, there is nothing about that in the format specification.

       
      • Maarten Brock

        Maarten Brock - 2020-07-21

        You can view this from two sides. To SDCC and its linker the ihx file describes how the rom is seen from the chip.

        Once you start using bank switching you should expect that it requires a bit more work. Maybe you upload the ihx to a bootloader that knows how to switch banks on the particular hardware.

        Maybe you must load it into an eeprom using an eeprom programmer that doesn't know anything about banks. In the latter case post process the ihx file with a tool like srecord.

         
        • Tony Pavlov

          Tony Pavlov - 2020-07-21

          i will explain you, why you are wrong only on "hourly fee" basis.

           
        • Sebastian Riedel

          I agree with tony that it’s desirable to represent the rom chip with the IHX file.
          Bank switching shouldn’t lead to any extra work.
          That way the linker should also be able to detect bank overflows etc.
          It’s also desirable to let _CODE_N default to the virtual address 0xN4000

          MBC1, MBC2, MBC3, MBC5, MBC7 all have the same bank size and their Banks >=1 mapped to 4000-7FFF, so we are in the quite comfortable situation, that we can use that as a standard on this platform.

          Clones of these are widely available and they are well supported by emulators.

          Only MBC6 does it differently, that one was only used in one real game and it would be hard to support since mapped banks can appear at two different places in the address space.

          Third party mappers are not that well documented.
          Multi game cartridges should rather be done with post processing, especially since those might mix sdcc-based games with games written in assembly.

           
          • Philipp Klaus Krause

            Is MBC6 like the Z180?

            Two windows in the address space, into which any bank can be mapped.
            Very convenient: Use one for functions (via __banked), the other for
            data (via __adresspace).
            So any function can access any data.

            Philipp

             
            • Sebastian Riedel

              Yes https://gbdev.io/pandocs/#mbc6

              The banks are also half the size of the other ones.
              The first windows is also at 0x4000, so it could theoretically be supported, but I would need a command line argument, that tells the the linker the bank size.
              The address translation could then be generalized into

                    if((addr & 0xFFFF0000) != 0)
                      {
                        addr = ((addr >> 16) * banksize);
                      }
              

              I assumed that the address is always the beginning of the bank. I could support 8KiB, 16KiB and 32KiB that way. Those are all bank sizes that where used in commecrial games and I would still default to 16KiB.
              It’s possible that there are no reproduction cartridges that use anything different than 16KiB banks.

               
            • Tony Pavlov

              Tony Pavlov - 2020-07-22

              MBC6 is a very rare thing and is not worth supporting. It is much more useful to support all other MBC's properly. That MBC6 only complicates things, you have to implement different modes in linker (or makebin as a workaround). Why not implement properly at least one style that covers 99% of the usecase? Or else that all will never be working.

               
              • Philipp Klaus Krause

                Having bank support will be useful for z180, z80, etc, too. And with MBC6 being very similar to Z180 banking, it could make sense to consider it.

                 
                • Tony Pavlov

                  Tony Pavlov - 2020-07-22

                  yes, but you have to write that support twice: for gbz80 and z180.

                  on z80 there exists very odd bank switching systems, that force switching, say bank4 from 0x4000 when say bank7 is switched from 0xA000. should that be supported "from the box" too (bank numbers are figurative, but i can check on my zx-spectrum clone)?

                  should you invent "selective intermittent banks concept" for that?

                   

                  Last edit: Tony Pavlov 2020-07-22
                  • Philipp Klaus Krause

                    For now (i.e. 4.1.0), it is probably sufficient to have full support toolchain for the common schemes on gbz80 only.

                    But from the compiler side further schemes and z80, etc. should be supported, even if users will be on their own for the linker.

                     
                    • Tony Pavlov

                      Tony Pavlov - 2020-07-22

                      compiler supports any possible systems now, because objects are position-independent. we are speaking about linker (or makebin as a workaround) in this thread, am i wrong?
                      if you add #pragma dataseg XXXX the support will be 100% complete in the compiler. That is the only uncovered case for now.

                       

                      Last edit: Tony Pavlov 2020-07-22
                    • Sebastian Riedel

                      So he z80 memory mappers have constant bank sizes and map them to a window of that size, too? (only difference being the way of selecting the bank, then)
                      I will implement a command line argument for bank size if it’s easy to implement, since I only have to change my constant into a variable.

                      I still have to find the place in sdld where I have to add this, so that jp, call, ld etc gets done based on the virtual address which represents the CPU viewpoint and .ihx, .map, .noi use the translated address within the ROM.

                       
                      • Tony Pavlov

                        Tony Pavlov - 2020-07-22

                        there is no need to declare bank size. that is mostly useless.

                         
                        • Sebastian Riedel

                          That’s true, but if it’s needed by other ports anyways I can try to add it while I’m on it.

                           
  • Maarten Brock

    Maarten Brock - 2020-07-21

    Hello Sebastian,

    Last week I fixed the .rel output already. I also tried to fix lnkarea() in lkarea.c already, but bumped into errors in the regressions tests.

    Maarten

     
    • Sebastian Riedel

      What errors did you bump into? There shouldn’t be any banking related regression tests for gbz80 yet.
      And how did you try to do the addresse translation?

      In makebin I use this code for translating virtual addresses to ROM addresses:

            if(gb && (addr & 0xFFFF0000) != 0)
              {
                // translate virtual addresses
                // all banks are located at 0x4000, upper 16 bits are the bank
                addr = (addr & 0xFFFF) - 0x4000 + ((addr >> 16) * 0x4000);
              }
      

      That translates

      0x14000->0x4000
      0x24000->0x8000
      0x34000->0xC000
      

      etc.

       

Log in to post a comment.

Monday.com Logo