home *** CD-ROM | disk | FTP | other *** search
- /*
- * gbe - gameboy emulator
- * Copyright (C) 1999 Chuck Mason, Steven Fuller
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * Chuck Mason <chuckjr@sinclair.net>
- * Steven Fuller <relnev@atdot.org>
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "rom.h"
- #include "vram.h"
- #include "mem.h"
- #include "regs.h"
- #include "cpu.h"
- #include "data.h"
- #include "amiga.h"
- #include "joypad.h"
-
- #define GAMEBOY_WIDTH (160 * gameboy_screen_mul)
- #define GAMEBOY_HEIGHT (144 * gameboy_screen_mul)
- #define GAMEBOY_TILEWIDTH 20
- #define GAMEBOY_TILEHEIGHT 18;
-
- /* LIGHTEST -------> DARKEST */
- static unsigned short int colors16[4] = { 0x6318, 0x4210, 0x2108, 0x0000 };
-
- static unsigned short int colors8[4] = { 219, 146, 73, 0 };
- static unsigned short int *colors;
-
- typedef struct _graphics_mode {
- int (*init)(char *);
- int (*close)();
- int (*create)(char *, int, int);
- int (*plot)(int, int, int);
- int (*blit)();
- int (*update)();
- } graphics_mode;
-
- graphics_mode graphic_modes[] = {
- #ifdef BUILD_AMIGA
- {
- gbe_init_amiga,
- gbe_close_amiga,
- gbe_create_window_amiga,
- gbe_plot_amiga,
- gbe_blit_amiga,
- gbe_poll_events_amiga
- },
- #endif
- };
-
- unsigned char graphic_sel = 0; /* 0 AmigaOS */
-
- short int (*fix_gbc_color) (short int color);
-
- /* Changes 0BBBBBGGGGGRRRRR to RRRGGGBB */
- short int fix_gbc_color8(short int color)
- {
- short int res = 0;
- unsigned char r, g, b;
-
- r = (color & 0x001c) << 3; /* 3 bits */
- g = (color & 0x0380) >> 5; /* 3 bits */
- b = (color & 0x6000) >> 13; /* 2 bits */
-
- res = r | g | b;
-
- return res;
- }
-
- /* Changes 0BBBBBGGGGGRRRRR to 0RRRRRGGGGGBBBBB */
- short int fix_gbc_color16(short int color)
- {
- short int res = 0;
- short r, g, b;
-
- r = (color & 0x001f) << 10; /* 5 bits */
- g = (color & 0x03e0); /* 5 bits */
- b = (color & 0x7c00) >> 10; /* 5 bits */
-
- res = r | g | b;
-
- return res;
- }
-
- void vram_set_color(int x, int c)
- {
- colors16[x] = colors8[x] = c;
- }
-
- void vram_plot(int x, int y, int color)
- {
- #if 0
- int nx, ny;
- int i, j;
- #endif
-
- if(x >= 160 || y >= 144)
- return;
- #if 0
- nx = x * gameboy_screen_mul;
- ny = y * gameboy_screen_mul;
-
- for(i = 0; i < gameboy_screen_mul; i++) {
- for(j = 0; j < gameboy_screen_mul; j++) {
- graphic_modes[graphic_sel].plot(nx+j, ny+i, color);
- }
- }
- #else
- graphic_modes[graphic_sel].plot(x, y, color);
- #endif
- }
-
-
- void vram_plot_line_sprites(int current_line)
- {
- /* Sprite tiles are always at $8000-$8FFF */
- char *tiles;
- char *sprptr;
- int sprcnt;
- int sprsize;
- int cntperline = 0;
- tiles = video_ram;
- sprptr = &sprite_oam[0xA0];
-
- sprsize = (LCDCONT & 0x04) ? 16 : 8;
-
- for(sprcnt = 40; sprcnt > 0; sprcnt--) {
- unsigned char x, xoff, yoff;
- unsigned char y;
- unsigned char tile, attr;
- unsigned char sprcolors;
- unsigned char yflip, xflip;
-
- attr = *--sprptr;
- tile = *--sprptr;
- x = *--sprptr;
- y = *--sprptr;
-
- if(x < 8) {
- xoff = 8 - x;
- x = 0;
- } else {
- xoff = 0;
- x -= 8;
- }
-
-
- if(y == 0) /* dont show sprite i guess */
- continue;
-
- y -= 16;
- yoff = 0;
-
- if(x >= 160)
- continue;
-
- sprcolors = (attr & 0x10) ? OBJ1PAL : OBJ0PAL;
- yflip = (attr & 0x40) ? 1 : 0;
- xflip = (attr & 0x20) ? 1 : 0;
-
- if(sprsize == 16)
- tile = tile & 0xFE; /* 8x16 ignores LS bit */
-
- if(abs(current_line - y) < sprsize && current_line >= y) {
- int nx;
- char *tileptr = &tiles[tile * 16];
-
- if(!yflip)
- tileptr += (abs(current_line - y)) * 2;
- else
- tileptr += ((sprsize - 1) - abs(current_line - y)) * 2;
-
- cntperline++;
-
- for(nx = xoff; nx < 8; nx++) {
- int bit1, bit2, color;
- int wbit = 0;
-
- if(!xflip)
- wbit = nx;
- else
- wbit = 7 - nx;
-
- bit1 = (*tileptr & (0x80 >> wbit)) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> wbit)) ? 1 : 0;
- color = (bit2 << 1) | bit1;
-
- switch(color) {
- case 0:
- break; /* transparency */
- vram_plot(x + nx, current_line, colors[(sprcolors & 0x03)]);
- break;
- case 1:
- vram_plot(x + nx, current_line, colors[(sprcolors & 0x0C) >> 2]);
- break;
- case 2:
- vram_plot(x + nx, current_line, colors[(sprcolors & 0x30) >> 4]);
- break;
- case 3:
- vram_plot(x + nx, current_line, colors[(sprcolors & 0xC0) >> 6]);
- break;
- }
- }
- }
- }
- }
-
- void vram_plot_line_sprites_color(int current_line)
- {
- /* Sprite tiles are always at $8000-$8FFF */
- char *tiles;
- char *sprptr;
- int sprcnt;
- int sprsize;
- int cntperline = 0;
- tiles = video_ram;
- sprptr = &sprite_oam[0xA0];
-
- sprsize = (LCDCONT & 0x04) ? 16 : 8;
-
- for(sprcnt = 40; sprcnt > 0; sprcnt--) {
- unsigned char x, xoff, yoff;
- unsigned char y;
- unsigned char tile, attr;
- unsigned char sprcolors;
- unsigned char yflip, xflip;
- unsigned char palette;
- unsigned char bank;
-
- attr = *--sprptr;
- tile = *--sprptr;
- x = *--sprptr;
- y = *--sprptr;
-
- if(x < 8) {
- xoff = 8 - x;
- x = 0;
- } else {
- xoff = 0;
- x -= 8;
- }
-
-
- if(y == 0) /* dont show sprite i guess */
- continue;
-
- y -= 16;
- yoff = 0;
-
- if(x >= 160)
- continue;
-
- sprcolors = (attr & 0x10) ? OBJ1PAL : OBJ0PAL;
- yflip = (attr & 0x40) ? 1 : 0;
- xflip = (attr & 0x20) ? 1 : 0;
- palette = (attr & 0x07);
- bank = (attr & 0x08) ? 1 : 0;
-
- if(sprsize == 16)
- tile = tile & 0xFE; /* 8x16 ignores LS bit */
-
- if(abs(current_line - y) < sprsize && current_line >= y) {
- int nx;
- char *tileptr = &tiles[tile * 16 + (bank * 0x2000)];
-
- if(!yflip)
- tileptr += (abs(current_line - y)) * 2;
- else
- tileptr += ((sprsize - 1) - abs(current_line - y)) * 2;
-
- cntperline++;
-
- for(nx = xoff; nx < 8; nx++) {
- int bit1, bit2, color;
- int wbit = 0;
-
- if(!xflip)
- wbit = nx;
- else
- wbit = 7 - nx;
-
- bit1 = (*tileptr & (0x80 >> wbit)) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> wbit)) ? 1 : 0;
- color = (bit2 << 1) | bit1;
-
- switch(color) {
- case 0:
- break; /* transparency */
- case 1:
- vram_plot(x + nx, current_line, fix_gbc_color(obj_palettes[palette][1]));
- break;
- case 2:
- vram_plot(x + nx, current_line, fix_gbc_color(obj_palettes[palette][2]));
- break;
- case 3:
- vram_plot(x + nx, current_line, fix_gbc_color(obj_palettes[palette][3]));
- break;
- }
- }
- }
- }
- }
-
- void vram_plot_line(unsigned char *table, int current_line)
- {
- char *tiles, *tileptr;
- int signnosign = 0;
-
- int x, y;
-
- if((LCDCONT & 0x10)) {
- signnosign = 0;
- tiles = &video_ram[0];
- } else {
- signnosign = 1;
- tiles = &video_ram[0x1000];
- }
-
-
- for(y = current_line, x = 0; x < 160; x += 8) {
- int bit1, bit2;
- int color;
- int nx;
- signed char tile;
- unsigned char scrolled_y = SCROLLY + y;
- unsigned char scrolled_x = SCROLLX + x;
-
- // tile = table[( (scrolled_y / 8) * 32 ) + (scrolled_x / 8)]; /* Find Tile # */
- tile = table[( (scrolled_y >> 3) << 5 ) + (scrolled_x >> 3)];
-
- if(signnosign && (tile & 0x80)) {
- /*tileptr = &tiles[tile * 16];*/
- tileptr = &tiles[tile << 4];
- } else {
- unsigned char t = tile; /* Lets make it an actual variable,
- * an odd reason, casting didn't work */
- // tileptr = &tiles[t * 16]; /* File Tile Data from # */
- tileptr = &tiles[t << 4];
- }
-
- tileptr += (scrolled_y % 8) * 2; /* Get Y Offset of Tile */
-
- for(nx = 0; nx < 8; nx++) {
- /*bit1 = (*tileptr & (0x80 >> (nx + (scrolled_x % 8)))) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> (nx + (scrolled_x % 8)))) ? 1 : 0; */
- bit1 = (*tileptr & (0x80 >> (nx + (scrolled_x & 0x07)))) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> (nx + (scrolled_x & 0x07)))) ? 1 : 0;
- color = (bit2 << 1) | bit1;
-
- switch(color) {
- case 0:
- vram_plot(x + nx, y, colors[(BGRDPAL & 0x03)]);
- break;
- case 1:
- vram_plot(x + nx, y, colors[(BGRDPAL & 0x0C) >> 2]);
- break;
- case 2:
- vram_plot(x + nx, y, colors[(BGRDPAL & 0x30) >> 4]);
- break;
- case 3:
- vram_plot(x + nx, y, colors[(BGRDPAL & 0xC0) >> 6]);
- break;
- }
- /*
- if((nx == 7 - (scrolled_x % 8)) && (scrolled_x % 8)) {
- x -= (scrolled_x % 8);
- break;
- }*/
- if((nx == 7 - (scrolled_x & 0x07)) && (scrolled_x & 0x07)) {
- x -= (scrolled_x & 0x07);
- break;
- }
- }
- }
- }
-
- void vram_plot_line_color(unsigned char *table, int current_line)
- {
- char *tiles, *tileptr;
- unsigned char attr;
- unsigned char pal;
-
- int signnosign = 0;
-
- int x, y;
-
- if((LCDCONT & 0x10)) {
- signnosign = 0;
- tiles = &video_ram[0];
- } else {
- signnosign = 1;
- tiles = &video_ram[0x1000];
- }
-
-
- for(y = current_line, x = 0; x < 160; x += 8) {
- int bit1, bit2;
- int color;
- int nx;
- signed char tile;
- unsigned char scrolled_y = SCROLLY + y;
- unsigned char scrolled_x = SCROLLX + x;
-
- tile = table[( (scrolled_y / 8) * 32 ) + (scrolled_x / 8)]; /* Find Tile # */
- attr = table[0x2000 + ( (scrolled_y / 8) * 32 ) + (scrolled_x / 8)]; /* Find attrs */
- pal = attr & 0x07;
-
- if(attr & 0x08) { /* Using bank 1 */
- if(signnosign && (tile & 0x80)) {
- tileptr = &tiles[0x2000 + tile * 16];
- } else {
- unsigned char t = tile;
- tileptr = &tiles[0x2000 + t * 16];
- }
- } else {
- if(signnosign && (tile & 0x80)) {
- tileptr = &tiles[tile * 16];
- } else {
- unsigned char t = tile; /* Lets make it an actual variable,
- * an odd reason, casting didn't work */
- tileptr = &tiles[t * 16]; /* File Tile Data from # */
- }
- }
-
- tileptr += (scrolled_y % 8) * 2; /* Get Y Offset of Tile */
-
- for(nx = 0; nx < 8; nx++) {
- bit1 = (*tileptr & (0x80 >> (nx + (scrolled_x % 8)))) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> (nx + (scrolled_x % 8)))) ? 1 : 0;
- color = (bit2 << 1) | bit1;
-
- switch(color) {
- case 0:
- vram_plot(x + nx, y, fix_gbc_color(bkg_palettes[pal][0]));
- break;
- case 1:
- vram_plot(x + nx, y, fix_gbc_color(bkg_palettes[pal][1]));
- break;
- case 2:
- vram_plot(x + nx, y, fix_gbc_color(bkg_palettes[pal][2]));
- break;
- case 3:
- vram_plot(x + nx, y, fix_gbc_color(bkg_palettes[pal][3]));
- break;
- }
- if((nx == 7 - (scrolled_x % 8)) && (scrolled_x % 8)) {
- x -= (scrolled_x % 8);
- break;
- }
- }
- }
- }
-
- int vram_plot_line_window(int current_line)
- {
- static int window_current_line = 0; /* This is for the Windows "static" line */
- static int last_current_line = 0;
-
- unsigned char *tableptr, *tiles, *tileptr;
- int signnosign;
-
- signnosign = 0;
-
- if(current_line == 0) /* Reset window to top of window or smth */
- window_current_line = 0;
- else if(last_current_line > current_line)
- window_current_line = 0;
-
- last_current_line = current_line;
-
- if(WNDPOSX >= 166) /* X >= 166 disables window */
- return 0;
-
- if((LCDCONT & 0x40)) /* The table refs to tiles */
- tableptr = &video_ram[0x1C00];
- else
- tableptr = &video_ram[0x1800];
-
- if((LCDCONT & 0x10)) { /* Actual tiles, (same as background) */
- signnosign = 0;
- tiles = video_ram;
- } else {
- signnosign = 1;
- tiles = &video_ram[0x1000];
- }
-
-
- /* The idea is this:
- display in the window (because its only 160x144 (close enuf)) from line
- window_current_line
- onto the screen at line
- current_line
- its an odd concept but the idea is this:
- say your window has only 4 rows of tiles in it.. if you were to display the entire
- window, it would cover the background.. but if youwere to disable the window at scanline
- 16, the first 2 tiles would have been displayed, and you re-enabled the window
- at line 124 (2 tiles from bottom), then the next 2 tiles in the window
- are displayed at that line.. it's a pretty cool concept, but a bitch
- to emulate.
- */
-
- if(current_line >= WNDPOSY) { /* Draw this portion single line :) */
- int y = window_current_line;
- int x;
-
- for(x = 0; x < 160; x += 8) {
- unsigned char tile;
- int nx, bit1, bit2, color;
-
- tile = tableptr[((y / 8) * 32) + (x / 8)];
-
- if(signnosign && (tile & 0x80)) {
- signed char t;
- t = tile;
- tileptr = &tiles[t * 16];
- } else
- tileptr = &tiles[tile * 16];
-
- tileptr += (y % 8) * 2;
-
- for(nx = 0; nx < 8; nx++) {
- bit1 = (*tileptr & (0x80 >> (nx + (x % 8)))) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> (nx + (x % 8)))) ? 1 : 0;
- color = (bit2 << 1) | bit1;
-
- switch(color) {
- case 0:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0x03)]);
- break;
- case 1:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0x0C) >> 2]);
- break;
- case 2:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0x30) >> 4]);
- break;
- case 3:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0xC0) >> 6]);
- break;
- }
- if((nx == 7 - (x % 8)) && (x % 8)) {
- x -= (x % 8);
- break;
- }
- }
-
- }
- window_current_line++;
- return 1;
- } else
- return 0;
- }
-
- int vram_plot_line_window_color(int current_line)
- {
- static int window_current_line = 0; /* This is for the Windows "static" line */
- static int last_current_line = 0;
-
- unsigned char *tableptr, *tiles, *tileptr;
- int signnosign;
-
- signnosign = 0;
-
- if(current_line == 0) /* Reset window to top of window or smth */
- window_current_line = 0;
- else if(last_current_line > current_line)
- window_current_line = 0;
-
- last_current_line = current_line;
-
- if(WNDPOSX >= 166) /* X >= 166 disables window */
- return 0;
-
- if((LCDCONT & 0x40)) /* The table refs to tiles */
- tableptr = &video_ram[0x1C00];
- else
- tableptr = &video_ram[0x1800];
-
- if((LCDCONT & 0x10)) { /* Actual tiles, (same as background) */
- signnosign = 0;
- tiles = video_ram;
- } else {
- signnosign = 1;
- tiles = &video_ram[0x1000];
- }
-
-
- /* The idea is this:
- display in the window (because its only 160x144 (close enuf)) from line
- window_current_line
- onto the screen at line
- current_line
- its an odd concept but the idea is this:
- say your window has only 4 rows of tiles in it.. if you were to display the entire
- window, it would cover the background.. but if youwere to disable the window at scanline
- 16, the first 2 tiles would have been displayed, and you re-enabled the window
- at line 124 (2 tiles from bottom), then the next 2 tiles in the window
- are displayed at that line.. it's a pretty cool concept, but a bitch
- to emulate.
- */
-
- if(current_line >= WNDPOSY) { /* Draw this portion single line :) */
- int y = window_current_line;
- int x;
-
- for(x = 0; x < 160; x += 8) {
- unsigned char tile;
- int nx, bit1, bit2, color;
-
- tile = tableptr[((y / 8) * 32) + (x / 8)];
-
- if(signnosign && (tile & 0x80)) {
- signed char t;
- t = tile;
- tileptr = &tiles[t * 16];
- } else
- tileptr = &tiles[tile * 16];
-
- tileptr += (y % 8) * 2;
-
- for(nx = 0; nx < 8; nx++) {
- bit1 = (*tileptr & (0x80 >> (nx + (x % 8)))) ? 1 : 0;
- bit2 = (*(tileptr + 1) & (0x80 >> (nx + (x % 8)))) ? 1 : 0;
- color = (bit2 << 1) | bit1;
-
- switch(color) {
- case 0:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0x03)]);
- break;
- case 1:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0x0C) >> 2]);
- break;
- case 2:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0x30) >> 4]);
- break;
- case 3:
- vram_plot(x + nx + (WNDPOSX > 0 ? WNDPOSX-7 : WNDPOSX), y + WNDPOSY, colors[(BGRDPAL & 0xC0) >> 6]);
- break;
- }
- if((nx == 7 - (x % 8)) && (x % 8)) {
- x -= (x % 8);
- break;
- }
- }
-
- }
- window_current_line++;
- return 1;
- } else
- return 0;
- }
-
- void vram_plot_screen()
- {
- char *table;
- int i;
-
- if(CURLINE >= 144)
- return;
-
- if(LCDCONT & 0x20) {
- if(!color_gameboy)
- i = vram_plot_line_window(CURLINE);
- else
- i = vram_plot_line_window_color(CURLINE);
- } else
- i = 0;
-
- if(LCDCONT & 0x01) {
- if((LCDCONT & 0x08))
- table = &video_ram[0x1C00];
- else
- table = &video_ram[0x1800];
-
- if(i == 0) {
- if(!color_gameboy)
- vram_plot_line(table, CURLINE);
- else
- vram_plot_line_color(table, CURLINE);
- }
- }
-
-
- if(LCDCONT & 0x02) {
- if(!color_gameboy)
- vram_plot_line_sprites(CURLINE);
- else
- vram_plot_line_sprites_color(CURLINE);
- }
- }
-
- void gbe_init_gfx()
- {
- int bitdepth;
-
- if(!(bitdepth = graphic_modes[graphic_sel].init(NULL))) {
- exit(1);
- }
-
- if(!graphic_modes[graphic_sel].create("gbe", GAMEBOY_WIDTH, GAMEBOY_HEIGHT)) {
- exit(1);
- }
-
- if(bitdepth == 2) {
- colors = colors16;
- fix_gbc_color = fix_gbc_color16;
- }
- else {
- colors = colors8;
- fix_gbc_color = fix_gbc_color8;
- }
-
- return;
- }
-
- void gbe_close_gfx()
- {
- graphic_modes[graphic_sel].close();
- }
-
- void vram_blit()
- {
- graphic_modes[graphic_sel].blit();
- }
-
- void vram_sysupdate()
- {
- joypad_update();
- graphic_modes[graphic_sel].update();
- }
-
- /* HBlank interrupt */
- void gameboy_hblank()
- {
- static int last_scanline = 0;
- /* static int did_vbl = 0; */
-
- DIVIDER += 18; /* unanomous value */
- IFLAGS &= 0xC0;
-
- if(CURLINE < 144) {
- LCDSTAT &= 0xFC;
- } else if(CURLINE >= 144) {
- LCDSTAT = (LCDSTAT & 0xFC) | 0x01;
-
- }
-
- if(TIMCONT & 0x04) {
- switch(TIMCONT & 0x03) {
- case 0:
- if((CURLINE - last_scanline) >= 3) {
- TIMECNT++;
- last_scanline = CURLINE;
- }
- break;
- case 1:
- if((CURLINE - last_scanline) >= 16) {
- if(TIMECNT <= (255 - 28))
- TIMECNT = 0;
- else
- TIMECNT += 28;
- last_scanline = CURLINE;
- }
- break;
- case 2:
- if((CURLINE - last_scanline) >= 64) {
- if(TIMECNT <= (255 - 7))
- TIMECNT = 0;
- else
- TIMECNT += 7;
- last_scanline = CURLINE;
- }
- break;
- case 3:
- TIMECNT += 2;
- if(TIMECNT == 1)
- TIMECNT = 0;
- break;
- default:
- printf("unknown frequency\n");
- break;
- }
- }
-
-
- if(gameboy_proc->PC.uw != VBLANK_INT &&
- CURLINE == CMPLINE && CURLINE <= 144 && (LCDSTAT & 0x44)) {
- IFLAGS |= 0x02; /* LCDC int */
- if((IENABLE & 0x02) && (gameboy_proc->IFF & 0x01)) {
- gameboy_proc->IFF &= ~0x01;
- gameboy_stack_write_word(gameboy_proc->PC.uw);
- gameboy_proc->PC.uw = 0x48;
- }
- }
-
- if(CURLINE < 155) {
- vram_sysupdate();
- vram_plot_screen();
- if(CURLINE == 0x90)
- gameboy_vblank();
- CURLINE++;
- } else if(CURLINE == 155) {
- CURLINE = 0;
- last_scanline = 0;
- }
-
- if(gameboy_proc->PC.uw != VBLANK_INT &&
- gameboy_proc->PC.uw != 0x48 &&
- TIMECNT == 0 &&
- TIMCONT & 0x04) {
- IFLAGS |= 0x04;
- TIMEMOD = 0xFF; /* TIMEMOD is loaded??? */
- if((IENABLE & 0x04) && (gameboy_proc->IFF & 0x01)) {
- gameboy_proc->IFF &= ~0x01;
- gameboy_stack_write_word(gameboy_proc->PC.uw);
- gameboy_proc->PC.uw = 0x50;
- }
- }
-
-
-
- if((SIOCONT & 0x80) &&
- gameboy_proc->PC.uw != VBLANK_INT &&
- gameboy_proc->PC.uw != 0x48 &&
- gameboy_proc->PC.uw != 0x50 &&
- CURLINE > 144) {
- SIOCONT &= 0x7F;
- SIODATA = 0;
- IFLAGS |= 0x08;
-
- if((IENABLE & 0x80) && (gameboy_proc->IFF & 0x01)) {
- printf("int tho!\n");
- gameboy_proc->IFF &= ~0x01;
- gameboy_stack_write_word(gameboy_proc->PC.uw);
- gameboy_proc->PC.uw = 0x58;
- return;
- }
- }
- }
-
- void gameboy_vblank()
- {
- /* Docs say this:
- The IME (aka gameboy_proc->IFF) flag is reset by DI and
- prohibits all interrupts. It is set by EI and acknoledges the
- interrupt setting by the IE (IENABLE, $FFFF) register.
-
- 1. When an interrupt is generated, the IF (IFLAGS, $FF0F)
- flag will be set.
- 2. If the IME flag is set & the corresponding IE flag is
- set, the following 3 steps are performed:
- 3. Reset the IME flag and prevelt all interrupts.
- 4. The PC (program counter) is pushed onto the stack.
- 5. Jump to the starting address of the interrupt.
-
- Resetting of the IF register, which was the cause of the
- interrupt, is done by hardware.
- */
-
- IFLAGS |= 0x01; /* Step 1 */
- if((IENABLE & 0x01) && (gameboy_proc->IFF & 0x01)) { /* Step 2 */
- gameboy_proc->IFF &= ~0x01; /* Step 3 */
- gameboy_stack_write_word(gameboy_proc->PC.uw); /* Step 4 */
- gameboy_proc->PC.uw = VBLANK_INT; /* Step 5 */
- }
-
- if(LCDCONT & 0x80)
- vram_blit();
-
- }
-
- void gameboy_do_dma()
- {
- unsigned short int address = (DMACONT << 8) & 0xFFF;
- unsigned char bank = DMACONT >> 4;
-
- if(gameboy_memory[bank])
- memcpy(sprite_oam, &gameboy_memory[bank][address], 0xA0);
- DMACONT = 0xE0;
- }
-