home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / gbe / mem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-12  |  18.9 KB  |  512 lines

  1. /*
  2.  *  gbe - gameboy emulator
  3.  *  Copyright (C) 1999  Chuck Mason, Steven Fuller
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18.  *
  19.  *
  20.  *  Chuck Mason <chuckjr@sinclair.net>
  21.  *  Steven Fuller <relnev@atdot.org>
  22.  */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h> /* 092299 */
  26. #include <time.h> /* 092299 */
  27.  
  28. #include "rom.h"
  29. #include "mem.h"
  30. #include "regs.h"
  31. #include "joypad.h"
  32. #include "cpu.h"
  33. #include "vram.h" /* 092299 */
  34.  
  35. unsigned char *gameboy_memory[16]; /* 0-F */
  36. unsigned char *video_ram    = (char *)NULL;  /* Mapped to 8 & 9 */
  37. unsigned char *internal_ram = (char *)NULL;  /* Mapped to B and C */
  38. unsigned char *bank_sixteen = (char *)NULL;  /* Mapped to F */
  39. unsigned char *sprite_oam   = (char *)NULL;  /* Mapped to FE00 */
  40. unsigned short int bkg_palettes[8][4];  /* 8 Palettes of 4 Colors Each */
  41. unsigned short int obj_palettes[8][4];  /* " */
  42.  
  43. unsigned char mbc1_ram_bank_enable = 0;      /* Default is disabled */
  44. unsigned char mbc1_address_line    = 0;
  45. unsigned short int mbc5_rom_select = 0;
  46.  
  47. void install_memory(char bank, void *fromwhere)
  48. {
  49.      gameboy_memory[(int)bank] = fromwhere;
  50. }
  51.  
  52. void memory_select_wram_bank(unsigned char bank, unsigned char where)
  53. {
  54.      char *ptr;
  55.  
  56.      if(!color_gameboy)  /* Useless on regular GB */
  57.           return;   
  58.      
  59.      if(bank == 0)
  60.           bank = 1;
  61.  
  62.      ptr = internal_ram + (bank * 0x1000);
  63.  
  64.      install_memory(where, ptr);
  65. }
  66.  
  67. void memory_select_vram_bank(unsigned char bank, unsigned char where)
  68. {
  69.      char *ptr;
  70.      
  71.      if(!color_gameboy)
  72.           return;
  73.      
  74.      if(bank > 2)
  75.           return;   /* uh oh? */
  76.      
  77.      ptr = video_ram + (bank * 0x2000);
  78.  
  79.      install_memory(where, ptr);
  80.      install_memory(where + 1, ptr + 0x1000);
  81. }
  82.  
  83.  
  84. int  initialize_memory()
  85. {
  86.      int i;
  87.      
  88.      for(i = 0; i < 16; i++) 
  89.           gameboy_memory[i] = (char *)NULL;
  90.  
  91.      if(!color_gameboy)  
  92.           video_ram = (char *)malloc(0x2000);     /* 8 Kilobyte Video Ram */
  93.      else
  94.           video_ram = (char *)malloc(0x4000);     /* 16 Kilobyte Video Ram */
  95.           
  96.      if(!video_ram)
  97.           return 0;
  98.      else {
  99.           if(!color_gameboy)
  100.                memset(video_ram, 0, 0x2000);
  101.           else
  102.                memset(video_ram, 0, 0x4000);
  103.      }
  104.      
  105.      
  106.      if(!color_gameboy)
  107.           internal_ram = (char *)malloc(0x2000);
  108.      else
  109.           internal_ram = (char *)malloc(0x8000);
  110.           
  111.      if(!internal_ram)
  112.           return 0;
  113.      else {
  114.           if(!color_gameboy)
  115.                memset(internal_ram, 0, 0x2000);
  116.           else
  117.                memset(internal_ram, 0, 0x8000);
  118.      }
  119.      
  120.      bank_sixteen = (char *)malloc(0x1000);
  121.  
  122.      if(!bank_sixteen)
  123.           return 0;
  124.      else
  125.           memset(bank_sixteen, 0, 0x1000);
  126.  
  127.      install_memory(8, video_ram + 0x0000);
  128.      install_memory(9, video_ram + 0x1000);
  129.  
  130.      install_memory(0x0A, NULL);   /* 8 Kilobyte Switchable RAM */
  131.      install_memory(0x0B, NULL);
  132.      
  133.      install_memory(0x0C, internal_ram + 0x0000); /* This is ok for both GB and GBC */
  134.      install_memory(0x0D, internal_ram + 0x1000);
  135.      install_memory(0x0E, internal_ram + 0x0000); /* Echo of Internal Ram */
  136.  
  137.      install_memory(0x0F, bank_sixteen);
  138.      
  139.      sprite_oam    = &gameboy_memory[0xF][0xE00];
  140.  
  141.      srand(time(NULL));  
  142.      return 1;
  143. }
  144.  
  145. void  free_memory()
  146. {
  147.      if(video_ram) {
  148.           free(video_ram);
  149.           install_memory(8, NULL);
  150.           install_memory(9, NULL);
  151.           video_ram = (char *)NULL;
  152.      }
  153.      if(internal_ram) {
  154.           free(internal_ram);
  155.           install_memory(0x0C, NULL);
  156.           install_memory(0x0D, NULL);
  157.           install_memory(0x0E, NULL);
  158.           internal_ram = (char *)NULL;
  159.      }
  160.      if(bank_sixteen) {
  161.           free(bank_sixteen);
  162.           install_memory(0xF, NULL);
  163.           bank_sixteen = (char *)NULL;
  164.      }
  165.      sprite_oam = (char *)NULL;    
  166. }
  167.  
  168.  
  169. unsigned char memory_read_byte(unsigned short int address)
  170. {
  171.      unsigned char bank;
  172.      unsigned short int where = 0;
  173.      
  174.      bank = (address & 0xF000) >> 12;
  175.  
  176.      if(bank == 0xF) {
  177.           where = address & 0x0FFF;
  178.  
  179. #ifdef MEM_DEBUG
  180.           printf("READ: ");
  181. #endif         
  182.           if(where == 0xFFF) {
  183. #ifdef MEM_DEBUG
  184.                printf("Interrupt Enable Register\n");
  185. #endif
  186.                return IENABLE;
  187.           } else if(where >= 0xF80) {
  188. #ifdef MEM_DEBUG
  189.                printf("Internal RAM\n");
  190. #endif
  191.                return gameboy_memory[bank][where];
  192.           } else if(where >= 0xF4C) {
  193. #ifdef MEM_DEBUG
  194.                printf("READ: Empty area???\n");
  195. #endif
  196.                return gameboy_memory[bank][where];
  197.           } else if(where >= 0xF00) {
  198. #ifdef MEM_DEBUG
  199.                printf("I/O Port $%02X\n", where & 0xFF);
  200. #endif
  201.                if(where == 0xF00) {
  202.                     if(!(JOYPAD & 0x20)) { /* Low bits */
  203.                          return ~(0xC0 | ((current_joypad & 0xF0) >> 4)) | 0x10;
  204.                     } else if(!(JOYPAD & 0x10)) {
  205.                          return ~(0xC0 | (current_joypad & 0x0F)) | 0x20;
  206.                     } else if(!(JOYPAD & 0x30)) { /* Weird? Reset then read? Odd! */
  207.                          return 0xFF;
  208.                     } else
  209.                          return 0;
  210.                } else if(where == 0xF41) {
  211.                     unsigned char ret;
  212.                     ret = LCDSTAT & 0xFC;
  213.                     if(CURLINE >= 144)
  214.                          ret |= 0x01;
  215.                     else if((ret & 0x08))
  216.                          ret &= ~0x03;
  217.                     return ret;
  218.                }
  219.                
  220.                return gameboy_memory[bank][where];
  221.           } else if(where >= 0xEA0) {
  222. #ifdef MEM_DEBUG
  223.                printf("Empty area 2???\n");
  224. #endif
  225.                return gameboy_memory[bank][where];
  226.           } else if(where >= 0xE00) {
  227. #ifdef MEM_DEBUG
  228.                printf("Sprite OAM\n");
  229. #endif
  230.                return gameboy_memory[bank][where];
  231.           } else {  /* Where < 0xE00 */
  232. #ifdef MEM_DEBUG
  233.                printf("0xF%03X\n", where);
  234. #endif
  235.                return gameboy_memory[0x0D][where];
  236.           }
  237.      } else {
  238.           if(bank == 0xA || bank == 0xB) {
  239.                if((cartridge_type >= 1 && cartridge_type <= 3) && mbc1_ram_bank_enable == 0)
  240.                     return 0; /* ignore read... */
  241.           }
  242.                                                                   
  243.           if((gameboy_memory[bank] != NULL) && (bank < 16))
  244.                return gameboy_memory[bank][address & 0xFFF];
  245.      }
  246.      return 0;
  247. }
  248.  
  249. unsigned short int memory_read_word(unsigned short int address)
  250. {
  251.      return (memory_read_byte(address) | (memory_read_byte(address+1) << 8));
  252. }
  253.  
  254. void memory_write_byte(unsigned short int address, unsigned char value)
  255. {
  256.      unsigned char bank;
  257.      unsigned short int where = 0;
  258.  
  259.      bank = (address & 0xF000) >> 12;
  260.      
  261.      if(bank == 0xF) {
  262.           where = address & 0x0FFF;
  263.  
  264. #ifdef MEM_DEBUG
  265.           printf("WRITE (%02X): ", value);
  266. #endif
  267.           if(where == 0xFFF) {
  268. #ifdef MEM_DEBUG
  269.                printf("Interrupt Enable Register\n");
  270. #endif
  271.                IENABLE = value;
  272.           } else if(where >= 0xF80) {
  273. #ifdef MEM_DEBUG
  274.                printf("Internal RAM\n");
  275. #endif
  276.                gameboy_memory[bank][where] = value;
  277.           } else if(where >= 0xF4C) {   
  278.                if(color_gameboy) {
  279.                     if(where == 0xF4F) {
  280.                          VBKREG = value & 0x01;
  281.                          memory_select_vram_bank(VBKREG, 0x08);
  282.                     } else if(where == 0xF70) {
  283.                          SVBKREG = value & 0x07;
  284.                          memory_select_wram_bank(SVBKREG, 0x0D);
  285.                     } else if(where == 0xF68) {
  286.                          BCPSREG = value & 0xBF;
  287.                     } else if(where == 0xF69) {
  288.                          unsigned char incpal;
  289.                          unsigned char pal;
  290.                          unsigned char col;
  291.                          unsigned char hl;
  292.                          
  293.                          incpal = (BCPSREG & 0x80) ? 1 : 0;
  294.                          pal    = (BCPSREG & 0x38) >> 3;
  295.                          col    = (BCPSREG & 0x06) >> 1;
  296.                          hl     = (BCPSREG & 0x01);
  297.                          
  298.                          if(hl) { /* BBBBB0GG */
  299.                               bkg_palettes[pal][col] = (bkg_palettes[pal][col] & 0x00FF) | (value << 8);
  300.                          } else { /* GGGRRRRR */
  301.                               bkg_palettes[pal][col] = (bkg_palettes[pal][col] & 0xFF00) | value;
  302.                          }
  303.                          /*printf("bkg palette data: %X:%c:pal[%d][%d]\n", value, (hl) ? 'h' : 'l', pal, col);*/
  304.                          if(incpal) {   /* Im sure this is possible by just incrementing the lower 6 bits! :( */
  305.                               if(hl) {
  306.                                    hl = 0;
  307.                                    if(col == 3) {
  308.                                         col = 0;
  309.                                         if(pal == 7)
  310.                                              pal = 0;
  311.                                         else
  312.                                              pal++;
  313.                                    } else
  314.                                         col++;
  315.                               } else
  316.                                    hl++;
  317.                               BCPSREG = 0x80 | hl | (col << 1) | (pal << 3);
  318.                          }
  319.                     } else if(where == 0xF6A) {
  320.                          OCPSREG = value & 0xBF;
  321.                     } else if(where == 0xF6B) {
  322.                          unsigned char incpal;
  323.                          unsigned char pal;
  324.                          unsigned char col;
  325.                          unsigned char hl;
  326.                     
  327.                          incpal = (OCPSREG & 0x80) ? 1 : 0;
  328.                          pal    = (OCPSREG & 0x38) >> 3;
  329.                          col    = (OCPSREG & 0x06) >> 1;
  330.                          hl     = (OCPSREG & 0x01);
  331.                     
  332.                          if(hl) { /* 0BBBBBGG */
  333.                               obj_palettes[pal][col] = (obj_palettes[pal][col] & 0x00FF) | (value << 8);
  334.                          } else { /* GGGRRRRR */
  335.                               obj_palettes[pal][col] = (obj_palettes[pal][col] & 0xFF00) | value;
  336.                          }
  337.  
  338.                          if(incpal) {   /* Im sure this is possible by just incrementing the lower 6 bits! :( */
  339.                               if(hl) {
  340.                                    hl = 0;
  341.                                    if(col == 3) {
  342.                                         col = 0;
  343.                                         if(pal == 7)
  344.                                              pal = 0;
  345.                                         else
  346.                                              pal++;
  347.                                    } else
  348.                                         col++;
  349.                               } else
  350.                                    hl++;
  351.                               OCPSREG = 0x80 | hl | (col << 1) | (pal << 3);
  352.                          }
  353.                     } else if(where == 0xF55) {
  354.                          unsigned short int dest;
  355.                          unsigned short int src;
  356.                          unsigned short int cnt;
  357.                          unsigned short int cntr;
  358.                          
  359.                          src = (HDMA1REG << 8) | (HDMA2REG & 0xF0);
  360.                          dest = ((HDMA3REG & 0x1F) << 11) | ((HDMA4REG & 0xF0));
  361.      printf("DMA5: %X From %X to %X\n", value, src, dest);
  362.                          cntr = ((value & 0x7F) + 1) * 16;
  363.                          for(cnt = 0; cnt < cntr; cnt++) {
  364.                               memory_write_byte(dest+cnt, memory_read_byte(src+cnt));
  365.                          }
  366.                     } else
  367.                          gameboy_memory[bank][where] = value;
  368.                } else
  369.                     gameboy_memory[bank][where] = value;
  370.           } else if(where >= 0xF00) {
  371. #ifdef MEM_DEBUG
  372.                printf("I/O Port %02X\n", where & 0xFF);
  373. #endif
  374.                if(where == 0xF40) {
  375.                     if((gameboy_memory[bank][where] & 0x80) && !(value & 0x80)) {
  376.                          if(CURLINE >= 144)
  377.                               gameboy_memory[bank][where] = value;
  378.                     } else {
  379.                          gameboy_memory[bank][where] = value;
  380.                     }
  381.                } else if(where == 0xF44) {
  382.                     printf("wrote %d\n", value);
  383.                     CURLINE = 0;
  384.                }
  385.                else if(where == 0xF00) {
  386.                     gameboy_memory[bank][where] = value;
  387.                } else if(where == 0xF07) {
  388.                     TIMECNT = 0;
  389.                     TIMEMOD = 0;
  390.                     TIMCONT = value;
  391.                } else if(where == 0xF02) {
  392.                     gameboy_memory[bank][where] = value;
  393.                } else if(where == 0xF46) {
  394.                     DMACONT = value;
  395.                     if(DMACONT < 0xE0)
  396.                          gameboy_do_dma();
  397.                } else 
  398.                     gameboy_memory[bank][where] = value;
  399.           } else if(where >= 0xEA0) {
  400. #ifdef MEM_DEBUG
  401.                printf("Empty area 2???\n");
  402. #endif
  403.                gameboy_memory[bank][where] = value;
  404.           } else if(where >= 0xE00) {
  405. #ifdef MEM_DEBUG
  406.                printf("Sprite OAM\n");
  407. #endif
  408.                gameboy_memory[bank][where] = value;
  409.           } else {
  410. #ifdef MEM_DEBUG
  411.                printf("0xF%03X\n", where);
  412. #endif
  413.                gameboy_memory[bank][where] = value;
  414.           }
  415.      } else {
  416.           if(bank < 8) {
  417.                if(cartridge_type >= TYPE_ROM_MBC1 && cartridge_type <= TYPE_ROM_MBC1_RAM_BATTERY) {
  418.                     if(address >= 0x6000 && address < 0x8000) {
  419.                          if(value & 0x01) {
  420.                               cartridge_mbc1 = MBC1_4M_32K;
  421.                               mbc1_address_line = 0;
  422.                          } else {
  423.                               cartridge_mbc1 = MBC1_16M_8K;
  424.                          }
  425.                     } else if(address >= 0x2000 && address < 0x4000) {
  426.                          unsigned short int bank = (value & 0x1F);
  427.  
  428.                          /*if(MBC1_16M_8K)
  429.                               bank |= (mbc1_address_line << 5);*/
  430.                               
  431.                          if(bank < 1)
  432.                               bank = 1;
  433.  
  434.                          rom_select_bank(bank, 4);
  435.                     }  else if(address >= 0x4000 && address < 0x6000) {
  436.                          switch(cartridge_mbc1) {
  437.                               case MBC1_16M_8K:
  438.                                    mbc1_address_line = (value & 0x03);
  439.                                    printf("address line = %d\n", mbc1_address_line);
  440.                                    break; /* fallthrough */
  441.                               case MBC1_4M_32K:
  442.                                    rom_select_ram_bank(value & 0x03);
  443.                                    break;
  444.                               default:
  445.                                    break;
  446.                          }
  447.                     } else if(address < 0x2000) {
  448.                          int res = value & 0x0F;
  449.                          if(res == 0x0A) {
  450.                               mbc1_ram_bank_enable = 1;
  451.                          } else {
  452.                               mbc1_ram_bank_enable = 0;
  453.                          }
  454.                     }
  455.                } else if(cartridge_type == TYPE_ROM_MBC2 || cartridge_type == TYPE_ROM_MBC2_BATTERY) {
  456.                     unsigned char ual = (address & 0xFF00) >> 8; /* Upper Address Line */
  457.                     
  458.                     if(address >= 0x2000 && address < 0x3000) {
  459.                          if(ual & 0x01) 
  460.                               rom_select_bank(value & 0x0F, 4);
  461.                     } else if(address < 0x2000) {
  462.                          if(ual & 0x01) {
  463.                               printf("ram bank %s\n", mbc1_ram_bank_enable ? "disabled" : "enabled");
  464.                               mbc1_ram_bank_enable = !mbc1_ram_bank_enable;
  465.                          }
  466.                     }                             
  467.                } else if(cartridge_type >= TYPE_ROM_MBC3 && cartridge_type <= TYPE_ROM_MBC3_RAM_BATTERY) {
  468.                     if(address >= 0x2000 && address <= 0x3FFF) {
  469.                          rom_select_bank(value & 0x7F, 4);
  470.                     } else if(address >= 0x4000 && address <= 0x5FFF) {
  471.                          rom_select_ram_bank(value & 0x3);
  472.                     }
  473.                } else if(cartridge_type >= TYPE_ROM_MBC5 && cartridge_type <= TYPE_ROM_MBC5_RAM_BATTERY) {
  474.                     if(address < 0x2000) {
  475.                          if(value == 0)
  476.                               mbc1_ram_bank_enable = 0;
  477.                          if(value == 0x0A)
  478.                               mbc1_ram_bank_enable = 1;
  479.                     } else if(address >= 0x2000 && address <= 0x2FFF) {    /* lower 8 bits of rom select */
  480.                          mbc5_rom_select = (mbc5_rom_select & 0xFF00) | value;
  481.                          rom_select_bank(mbc5_rom_select, 4);
  482.                     } else if(address >= 0x3000 && address <= 0x3FFF) {
  483.                          mbc5_rom_select = (value & 0x01) << 8 | (mbc5_rom_select & 0x00FF);
  484.                          rom_select_bank(mbc5_rom_select, 4);
  485.                     } else if(address >= 0x4000 && address < 0x6000) {
  486.                          rom_select_ram_bank(value & 0x0F); /* gets a total of 15 banks */
  487.                     }
  488.                }
  489.                
  490.                return;
  491.           } else if(bank == 0xA || bank == 0xB) {
  492.                /* mbc1 */
  493.                if(cartridge_type >= 1 && cartridge_type <= 3 && mbc1_ram_bank_enable == 0)
  494.                     return;   /* ignore write.. */
  495.                if(cartridge_type == TYPE_ROM_MBC2 || (cartridge_type == TYPE_ROM_MBC2_BATTERY && mbc1_ram_bank_enable == 0))
  496.                     return; /* ignore write.. */
  497.                if(cartridge_type >= TYPE_ROM_MBC5 && cartridge_type <= TYPE_ROM_MBC5_RAM_BATTERY && mbc1_ram_bank_enable == 0)
  498.                     return;
  499.                if(gameboy_memory[bank])
  500.                     gameboy_memory[bank][address & 0xFFF] = value;
  501.           }
  502.           else if(gameboy_memory[bank])
  503.                gameboy_memory[bank][address & 0xFFF] = value;
  504.      }
  505. }
  506.  
  507. void memory_write_word(unsigned short int address, unsigned short int value)
  508. {
  509.      memory_write_byte(address, value & 0xFF);
  510.      memory_write_byte(address + 1, (value & 0xFF00) >> 8);
  511. }
  512.