diff --git a/src/computer.c b/src/computer.c index de0d144..049084d 100644 --- a/src/computer.c +++ b/src/computer.c @@ -1,1663 +1,1389 @@ -/* - * Copyright 2003-2009 (C) Raster Software Vigo (Sergio Costas) - * This file is part of FBZX - * - * FBZX 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 3 of the License, or - * (at your option) any later version. - * - * FBZX 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, see . - * - */ - -#include "z80free/Z80free.h" -#include "computer.h" -#include "emulator.h" -#include "menus.h" -#include "characters.h" -#include "sound.h" -#include -#include -#include -#include -#include -#include "tape.h" -#include "microdrive.h" - -#ifdef DEBUG -extern FILE *fdebug; -#define printf(...) fprintf(fdebug,__VA_ARGS__) -#else - #ifdef GEKKO - #define printf(...) - #endif -#endif - -/* Returns the bus value when reading a port without a periferial */ - -inline byte bus_empty () { - - if (ordenador.mode128k != 3) - return (ordenador.bus_value); - else - return (255); // +2A and +3 returns always 255 -} - -/* calls all the routines that emulates the computer, runing them for 'tstados' - tstates */ - -inline void emulate (int tstados) { - - if((procesador.I>=0x40)&&(procesador.I<=0x7F)) { - ordenador.screen_snow=1; - } else - ordenador.screen_snow=0; - show_screen (tstados); - play_ay (tstados); - play_sound (tstados); - tape_read (ordenador.tap_file, tstados); - microdrive_emulate(tstados); - if (!ordenador.pause) { - if (ordenador.tape_readed) - ordenador.sound_bit = 1; - else - ordenador.sound_bit = 0; // if not paused, asign SOUND_BIT the value of tape - } -} - -void computer_init () { - - int bucle; - - ordenador.bus_counter = 0; - ordenador.port254 = 0; - ordenador.issue = 3; - ordenador.mode128k = 0; - ordenador.joystick = 0; - - ordenador.tape_readed = 0; - ordenador.pause = 1; // tape stop - ordenador.tape_fast_load = 1; // fast load by default - ordenador.tape_current_mode = TAP_TRASH; - ordenador.tap_file = NULL; - - ordenador.osd_text[0] = 0; - ordenador.osd_time = 0; - - ordenador.other_ret = 0; - - ordenador.s8 = ordenador.s9 = ordenador.s10 = ordenador.s11 = - ordenador.s12 = ordenador.s13 = ordenador.s14 = - ordenador.s15 = 0xFF; - ordenador.tab_extended=0; - ordenador.esc_again=0; - - ordenador.js = 0x00; - - for (bucle = 0; bucle < 16; bucle++) - ordenador.ay_registers[bucle] = 0; - ordenador.ay_emul = 0; - ordenador.aych_a = 0; - ordenador.aych_b = 0; - ordenador.aych_c = 0; - ordenador.aych_n = 0; - ordenador.aych_envel = 0; - ordenador.vol_a = 0; - ordenador.vol_b = 0; - ordenador.vol_c = 0; - ordenador.tst_ay = 0; - ordenador.tst_ay2 = 0; - - ordenador.ayval_a = 0; - ordenador.ayval_b = 0; - ordenador.ayval_c = 0; - ordenador.ayval_n = 0; - ordenador.ay_envel_value = 0; - ordenador.ay_envel_way = 0; - - ordenador.tape_loop_counter = 0; - ordenador.kbd_buffer_pointer = 0; -} - -void computer_set_palete() { - - SDL_Color colores[16]; - - if (ordenador.bw==0) { - // Color mode - - colores[0].r = 0; - colores[0].g = 0; - colores[0].b = 0; - colores[1].r = 0; - colores[1].g = 0; - colores[1].b = 192; - colores[2].r = 192; - colores[2].g = 0; - colores[2].b = 0; - colores[3].r = 192; - colores[3].g = 0; - colores[3].b = 192; - colores[4].r = 0; - colores[4].g = 192; - colores[4].b = 0; - colores[5].r = 0; - colores[5].g = 192; - colores[5].b = 192; - colores[6].r = 192; - colores[6].g = 192; - colores[6].b = 0; - colores[7].r = 192; - colores[7].g = 192; - colores[7].b = 192; - colores[8].r = 0; - colores[8].g = 0; - colores[8].b = 0; - colores[9].r = 0; - colores[9].g = 0; - colores[9].b = 255; - colores[10].r = 255; - colores[10].g = 0; - colores[10].b = 0; - colores[11].r = 255; - colores[11].g = 0; - colores[11].b = 255; - colores[12].r = 0; - colores[12].g = 255; - colores[12].b = 0; - colores[13].r = 0; - colores[13].g = 255; - colores[13].b = 255; - colores[14].r = 255; - colores[14].g = 255; - colores[14].b = 0; - colores[15].r = 255; - colores[15].g = 255; - colores[15].b = 255; - - SDL_SetColors (ordenador.screen, colores, 16, 16); // set 16 colors from the 16th - - if (ordenador.bpp!=1) { - colors[0]=SDL_MapRGB(screen->format,0,0,0); - colors[1]=SDL_MapRGB(screen->format,0,0,192); - colors[2]=SDL_MapRGB(screen->format,192,0,0); - colors[3]=SDL_MapRGB(screen->format,192,0,192); - colors[4]=SDL_MapRGB(screen->format,0,192,0); - colors[5]=SDL_MapRGB(screen->format,0,192,192); - colors[6]=SDL_MapRGB(screen->format,192,192,0); - colors[7]=SDL_MapRGB(screen->format,192,192,192); - colors[8]=SDL_MapRGB(screen->format,0,0,0); - colors[9]=SDL_MapRGB(screen->format,0,0,255); - colors[10]=SDL_MapRGB(screen->format,255,0,0); - colors[11]=SDL_MapRGB(screen->format,255,0,255); - colors[12]=SDL_MapRGB(screen->format,0,255,0); - colors[13]=SDL_MapRGB(screen->format,0,255,255); - colors[14]=SDL_MapRGB(screen->format,255,255,0); - colors[15]=SDL_MapRGB(screen->format,255,255,255); - } - } else { - - // B&W mode - - colores[0].r = 0; - colores[0].g = 0; - colores[0].b = 0; - - colores[1].r = 22; - colores[1].g = 22; - colores[1].b = 22; - - colores[2].r = 57; - colores[2].g = 57; - colores[2].b = 57; - - colores[3].r = 79; - colores[3].g = 79; - colores[3].b = 79; - - colores[4].r = 113; - colores[4].g = 113; - colores[4].b = 113; - - colores[5].r = 135; - colores[5].g = 135; - colores[5].b = 135; - - colores[6].r = 160; - colores[6].g = 160; - colores[6].b = 160; - - colores[7].r = 192; - colores[7].g = 192; - colores[7].b = 192; - - colores[8].r = 0; - colores[8].g = 0; - colores[8].b = 0; - - colores[9].r = 29; - colores[9].g = 29; - colores[9].b = 29; - - colores[10].r = 76; - colores[10].g = 76; - colores[10].b = 76; - - colores[11].r = 105; - colores[11].g = 105; - colores[11].b = 105; - - colores[12].r = 150; - colores[12].g = 150; - colores[12].b = 150; - - colores[13].r = 179; - colores[13].g = 179; - colores[13].b = 179; - - colores[14].r = 226; - colores[14].g = 226; - colores[14].b = 226; - - colores[15].r = 255; - colores[15].g = 255; - colores[15].b = 255; - - SDL_SetColors (ordenador.screen, colores, 16, 16); // set 16 colors from the 16th - - if (ordenador.bpp!=1) { - colors[0]=SDL_MapRGB(screen->format,0,0,0); - colors[1]=SDL_MapRGB(screen->format,22,22,22); - colors[2]=SDL_MapRGB(screen->format,57,57,57); - colors[3]=SDL_MapRGB(screen->format,79,79,79); - colors[4]=SDL_MapRGB(screen->format,113,113,113); - colors[5]=SDL_MapRGB(screen->format,135,135,135); - colors[6]=SDL_MapRGB(screen->format,160,160,160); - colors[7]=SDL_MapRGB(screen->format,192,192,192); - colors[8]=SDL_MapRGB(screen->format,0,0,0); - colors[9]=SDL_MapRGB(screen->format,29,29,29); - colors[10]=SDL_MapRGB(screen->format,76,76,76); - colors[11]=SDL_MapRGB(screen->format,105,105,105); - colors[12]=SDL_MapRGB(screen->format,150,150,150); - colors[13]=SDL_MapRGB(screen->format,179,179,179); - colors[14]=SDL_MapRGB(screen->format,226,226,226); - colors[15]=SDL_MapRGB(screen->format,255,255,255); - } - } - - unsigned int c; - - for(c=0x10;c<60;c++) { - colors[c]=0x00000000; - } - - if (ordenador.bpp==1) { - unsigned int v; - for (c=0x10;c<0x60;c++) { - v=c+((c<<8)&0x0000FF00)+((c<<16)&0x00FF0000)+((c<<24)&0xFF000000); - colors[c-0x10]=v; - } - } - for(c=0;c<64;c++) { - set_palete_entry((unsigned char)c,ordenador.ulaplus_palete[c]); - } -} - -/* Registers the screen surface where the Spectrum will put the picture, -prepares the palette and creates two arrays (translate and translate2) -that gives the memory address for each scan */ - -void register_screen (SDL_Surface * pantalla) { - - //int resx,resy; - int bucle, bucle2, bucle3, bucle4, bucle5; - - // we prepare the scanline transform arrays - - bucle5 = 0; - for (bucle = 0; bucle < 3; bucle++) - for (bucle2 = 0; bucle2 < 8; bucle2++) - for (bucle3 = 0; bucle3 < 8; bucle3++) - for (bucle4 = 0; bucle4 < 32; bucle4++) { - ordenador.translate[bucle5] = - 147456 + bucle * 2048 + - bucle2 * 32 + bucle3 * 256 + - bucle4; - ordenador.translate2[bucle5] = - 153600 + bucle * 256 + - bucle2 * 32 + bucle4; - bucle5++; - } - ordenador.tstados_counter = 0; - - ordenador.screen = pantalla; - - ordenador.border = 0; - ordenador.currline = 0; - ordenador.currpix = 0; - ordenador.flash = 0; - - //resx = ordenador.screen->w; - //resy = ordenador.screen->h; - - switch (ordenador.zaurus_mini) { - case 0: - ordenador.init_line = 0; - ordenador.next_line = 640; - ordenador.next_scanline = 640; - ordenador.first_line = 40; - ordenador.last_line = 280; - ordenador.first_pixel = 16; - ordenador.last_pixel = 336; - ordenador.next_pixel = 1; - ordenador.jump_pixel = 16; - break; - case 1: - ordenador.init_line = 65; - ordenador.next_line = 160; - ordenador.next_scanline = 160; - ordenador.first_line = 40; - ordenador.last_line = 280; - ordenador.first_pixel = 0; - ordenador.last_pixel = 351; - ordenador.next_pixel = 1; - ordenador.jump_pixel = 8; - break; - case 2: - ordenador.init_line = 479; - ordenador.next_line = -(307202); - ordenador.next_scanline = -1; - ordenador.first_line = 40; - ordenador.last_line = 280; - ordenador.first_pixel = 16; - ordenador.last_pixel = 336; - ordenador.next_pixel = 480; - ordenador.jump_pixel = 7680; - break; - case 3: - ordenador.init_line = 0; - ordenador.next_line = 0; - ordenador.next_scanline = 0; - ordenador.first_line = 40; - ordenador.last_line = 280; - ordenador.first_pixel = 0; - ordenador.last_pixel = 319; - ordenador.next_pixel = 1; - ordenador.jump_pixel = 4; - break; - } - - ordenador.next_line*=ordenador.bpp; - ordenador.next_scanline*=ordenador.bpp; - ordenador.init_line*=ordenador.bpp; - ordenador.next_pixel*=ordenador.bpp; - ordenador.jump_pixel*=ordenador.bpp; - - computer_set_palete(); - - ordenador.pixel = ((unsigned char *) (ordenador.screen->pixels)) + ordenador.init_line; - ordenador.interr = 0; - - ordenador.p_translt = ordenador.translate; - ordenador.p_translt2 = ordenador.translate2; - - ordenador.contador_flash = 0; - ordenador.readed = 0; - - ordenador.contended_zone=0; - ordenador.cicles_counter=0; - - ordenador.tstados_counter_sound = 0; - ordenador.current_buffer = sound[0]; - ordenador.num_buff = 0; // first buffer - ordenador.sound_cuantity = 0; - ordenador.sound_current_value = 0; - ordenador.pixancho = 447; - ordenador.pixalto = 311; // values for 48K mode -} - -void set_memory_pointers () { - - static unsigned int rom, ram; - - // assign the offset for video page - - if (ordenador.mport1 & 0x08) - ordenador.video_offset = 32768; // page 7 - else - ordenador.video_offset = 0; // page 5 - - // assign ROMs and, if in special mode, RAM for the whole blocks - - if ((ordenador.mode128k == 3)) { - if (ordenador.mport2 & 0x01) { // +2A/+3 special mode - ram = (unsigned int) (ordenador.mport1 & 0x06); // bits 1&2 - switch (ram) { - case 0: - ordenador.block0 = ordenador.memoria + 65536; - ordenador.block1 = ordenador.memoria + 65536; - ordenador.block2 = ordenador.memoria + 65536; - ordenador.block3 = ordenador.memoria + 65536; - break; - case 2: - ordenador.block0 = ordenador.memoria + 131072; - ordenador.block1 = ordenador.memoria + 131072; - ordenador.block2 = ordenador.memoria + 131072; - ordenador.block3 = ordenador.memoria + 131072; - break; - case 4: - ordenador.block0 = ordenador.memoria + 131072; - ordenador.block1 = ordenador.memoria + 131072; - ordenador.block2 = ordenador.memoria + 131072; - ordenador.block3 = ordenador.memoria + 65536; - break; - case 6: - ordenador.block0 = ordenador.memoria + 131072; - ordenador.block1 = ordenador.memoria + 163840; - ordenador.block2 = ordenador.memoria + 131072; - ordenador.block3 = ordenador.memoria + 65536; - break; - } - return; - } else { // ROMs for +2A/+3 normal mode - rom = 0; - if (ordenador.mport1 & 0x10) - rom++; - if (ordenador.mport2 & 0x04) - rom += 2; - // assign the first block pointer to the right block bank - ordenador.block0 = ordenador.memoria + (16384 * rom); - } - } else { // ROMs for 128K/+2 mode - if (ordenador.mport1 & 0x10) - ordenador.block0 = ordenador.memoria + 16384; - else - ordenador.block0 = ordenador.memoria; - } - - // RAMs for 128K/+2 mode, and +2A/+3 in normal mode - - ordenador.block1 = ordenador.memoria + 131072; // page 5 minus 16384 - ordenador.block2 = ordenador.memoria + 65536; // page 2 minus 32768 - - ram = 1 + ((unsigned int) (ordenador.mport1 & 0x07)); // RAM page for block3 plus 1 - ordenador.block3 = ordenador.memoria + (16384 * ram); // page n minus 49152 -} - -/* Paints the spectrum screen during the TSTADOS tstates that the Z80 used -to execute last instruction */ - -inline void show_screen (int tstados) { - - static unsigned char temporal, ink, paper, fflash, tmp2; - - ordenador.tstados_counter += tstados; - ordenador.cicles_counter += tstados; - - if (curr_frames!=jump_frames) { - if (ordenador.tstados_counter>=69888) { - ordenador.tstados_counter-=69888; - ordenador.interr = 1; - curr_frames++; - } - return; - } - - fflash = 0; // flash flag - while (ordenador.tstados_counter > 3) { - ordenador.tstados_counter -= 4; - - // test if current pixel is for border or for user area - - if ((ordenador.currline < 64) || (ordenador.currline > 255) - || (ordenador.currpix < 48) || (ordenador.currpix > 303)) { - - // is border - - ordenador.contended_zone=0; // no contention here - if (ordenador.ulaplus) { - paint_pixels (255, ordenador.border+24, 0); // paint 8 pixels with BORDER color - } else { - paint_pixels (255, ordenador.border, 0); // paint 8 pixels with BORDER color - } - - ordenador.bus_value = 255; - - } else { - - // is user area. We search for ink and paper colours - - ordenador.contended_zone=1; // can have contention - - temporal = ordenador.memoria[(*ordenador.p_translt2) + ordenador.video_offset]; // attributes - ordenador.bus_value = temporal; - ink = temporal & 0x07; // ink colour - paper = (temporal >> 3) & 0x07; // paper colour - if (ordenador.ulaplus) { - tmp2=0x10+((temporal>>2)&0x30); - ink+=tmp2; - paper+=8+tmp2; - } else { - if (temporal & 0x40) { // bright flag? - ink += 8; - paper += 8; - } - fflash = temporal & 0x80; // flash flag - } - - // Snow Effect - - if(ordenador.screen_snow) { - temporal = ordenador.memoria[(((*ordenador.p_translt) + (ordenador.video_offset))&0xFFFFFF00)+(procesador.R)]; // data with snow - ordenador.screen_snow=0; // no more snow for now - } else - temporal = ordenador.memoria[(*ordenador.p_translt) + ordenador.video_offset]; // data - - ordenador.p_translt++; - ordenador.p_translt2++; - if ((fflash) && (ordenador.flash)) - paint_pixels (temporal, paper, ink); // if FLASH, invert PAPER and INK - else - paint_pixels (temporal, ink, paper); - } - ordenador.currpix += 8; - if (ordenador.currpix > ordenador.pixancho) { - ordenador.currpix = 0; - ordenador.currline++; - if (ordenador.currline > ordenador.first_line) { // ordenador.first_line) - ordenador.pixel += ordenador.next_line; // ordenador.next_line; - } - } - - if ((ordenador.currline > ordenador.pixalto)&&(ordenador.currpix>=64)) { - ordenador.currpix=64; - if (ordenador.osd_time) { - ordenador.osd_time--; - if (ordenador.osd_time==0) { - ordenador.tab_extended=0; - ordenador.esc_again=0; - } - - if (ordenador.osd_time) - print_string (ordenador.screenbuffer,ordenador.osd_text, -1,450, 12, 0,ordenador.screen_width); - else { - if (ordenador.zaurus_mini==0) - print_string (ordenador.screenbuffer," ",-1, 450, 12, 0,ordenador.screen_width); - else - print_string (ordenador.screenbuffer," ",-1, 450, 12, 0,ordenador.screen_width); - } - } - - if (ordenador.mustlock) { - SDL_UnlockSurface (ordenador.screen); - SDL_Flip (ordenador.screen); - SDL_LockSurface (ordenador.screen); - } else { - SDL_Flip (ordenador.screen); - } - - curr_frames=0; - ordenador.currline = 0; - ordenador.interr = 1; - ordenador.cicles_counter=0; - ordenador.pixel = ((unsigned char *) (ordenador.screen->pixels))+ordenador.init_line; // +ordenador.init_line; - ordenador.p_translt = ordenador.translate; - ordenador.p_translt2 = ordenador.translate2; - ordenador.contador_flash++; - if (ordenador.contador_flash == 16) { - ordenador.flash = 1 - ordenador.flash; - ordenador.contador_flash = 0; - } - } - } -} - - -/* PAINT_PIXELS paints one byte with INK color for 1 bits and PAPER color -for 0 bits, and increment acordingly the pointer PIXEL */ - -inline void paint_pixels (unsigned char octet,unsigned char ink, unsigned char paper) { - - static int bucle,valor,*p; - static unsigned char mask; - - if ((ordenador.currpix < 16) || (ordenador.currpix >= 336) - || (ordenador.currline < 40) || (ordenador.currline >= 280)) - return; - - mask = 0x80; - for (bucle = 0; bucle < 8; bucle++) { - valor = (octet & mask) ? (int) ink : (int) paper; - p=(colors+valor); - - paint_one_pixel((unsigned char *)p,ordenador.pixel); - if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3)&&(ordenador.dblscan)) { - paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline); - } - ordenador.pixel+=ordenador.next_pixel; - if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3)) { - paint_one_pixel((unsigned char *)p,ordenador.pixel); - if (ordenador.dblscan) { - paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline); - } - ordenador.pixel+=ordenador.next_pixel; - } - mask = ((mask >> 1) & 0x7F); - } -} - -inline void paint_one_pixel(unsigned char *colour,unsigned char *address) { - - #if BYTE_ORDER == LITTLE_ENDIAN - switch(ordenador.bpp) { - case 1: - *address=*colour; - break; - case 3: - *(address++)=*(colour++); - case 2: - *(address++)=*(colour++); - *(address++)=*(colour++); - break; - case 4: - *((unsigned int *)address)=*((unsigned int *)colour); - break; - } - #else //BIG ENDIAN - switch(ordenador.bpp) { - case 1: - *address=*(colour+3); - break; - case 3: - *(address++)=*(colour+1); - case 2: - *(address++)=*(colour+2); - *(address++)=*(colour+3); - break; - case 4: - *((unsigned int *)address)=*((unsigned int *)colour); - break; - } - #endif - -} - -// Read the keyboard and stores the flags - -inline void read_keyboard (SDL_Event *pevento2) { - - unsigned int temporal_io; - SDL_Event evento,evento2,*pevento; - Sint16 valor; - Uint8 eje; - static int countdown; - - - if (ordenador.kbd_buffer_pointer) - { - if (countdown) - countdown--; - else - { - if (ordenador.kbd_buffer_pointer != 1) - { - SDL_PushEvent(&ordenador.keyboard_buffer[ordenador.kbd_buffer_pointer-2]); - ordenador.kbd_buffer_pointer--; - countdown=5; - } - else - { - ordenador.kbd_buffer_pointer = 0; - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) - ordenador.pause = 0; - } - } - } - - if (pevento2==NULL) { - pevento=&evento; - if (!SDL_PollEvent (&evento)) - return; - } else { - pevento=pevento2; - } - - if (pevento->type==SDL_QUIT) { - salir = 0; - return; - } - - if (pevento->type==SDL_JOYBUTTONDOWN) { - pevento->type=SDL_KEYDOWN; - pevento->key.keysym.sym=SDLK_MENU; // emulate pressing the MENU key - } - - if (pevento->type==SDL_JOYBUTTONUP) { - pevento->type=SDL_KEYUP; - pevento->key.keysym.sym=SDLK_MENU; // emulate depressing the MENU key - } - - if (pevento->type==SDL_JOYAXISMOTION) { - eje=pevento->jaxis.axis; - valor=pevento->jaxis.value; - - evento2.type=SDL_KEYUP; - if ((valor<16384)&&(valor>-16384)) { // JoyStick centered - pevento->type=SDL_KEYUP; - if (eje==1) { - evento2.key.keysym.sym=SDLK_DOWN; - pevento->key.keysym.sym=SDLK_UP; // pull up both keys - read_keyboard(&evento2); - } - if (eje==0) { - evento2.key.keysym.sym=SDLK_LEFT; - pevento->key.keysym.sym=SDLK_RIGHT; - read_keyboard(&evento2); - } - } else { // JoyStick moved - if (eje==0) { - if (valor>=0) { - evento2.key.keysym.sym=SDLK_LEFT; // pull up LEFT - read_keyboard(&evento2); - pevento->key.keysym.sym=SDLK_RIGHT; // and press RIGHT - } else { - evento2.key.keysym.sym=SDLK_RIGHT; // pull up RIGHT - read_keyboard(&evento2); - pevento->key.keysym.sym=SDLK_LEFT; // and press LEFT - } - } - if (eje==1) { - if (valor<0) { - evento2.key.keysym.sym=SDLK_DOWN; // pull up DOWN - pevento->key.keysym.sym=SDLK_UP; // and press UP - read_keyboard(&evento2); - } else { - evento2.key.keysym.sym=SDLK_UP; // pull up UP - pevento->key.keysym.sym=SDLK_DOWN; // and press DOWN - read_keyboard(&evento2); - } - } - pevento->type=SDL_KEYDOWN; - } - } - - if ((pevento->type != SDL_KEYDOWN) && (pevento->type != SDL_KEYUP)) - return; - - ordenador.k8 = ordenador.k9 = ordenador.k10 = ordenador.k11 = - ordenador.k12 = ordenador.k13 = ordenador.k14 = - ordenador.k15 = 0; - ordenador.jk = 0; - - temporal_io = (unsigned int) pevento->key.keysym.sym; - - if ((pevento->type==SDL_KEYUP)&&(temporal_io==SDLK_TAB)) { - if (ordenador.tab_extended==0) { - ordenador.tab_extended=1; - strcpy(ordenador.osd_text,"Function Key mode on"); - ordenador.osd_time=100; - return; - } else { - ordenador.tab_extended=0; - ordenador.osd_time=0; - return; - } - } - - if ((pevento->type==SDL_KEYDOWN)&&(ordenador.tab_extended==1)) - return; - - if ((pevento->type==SDL_KEYUP)&&(ordenador.tab_extended==1)) { - ordenador.tab_extended=0; - ordenador.osd_time=0; - switch(temporal_io) { - case SDLK_1: - temporal_io=SDLK_F1; - break; - case SDLK_2: - temporal_io=SDLK_F2; - break; - case SDLK_3: - temporal_io=SDLK_F3; - break; - case SDLK_4: - temporal_io=SDLK_F4; - break; - case SDLK_5: - temporal_io=SDLK_F5; - break; - case SDLK_6: - temporal_io=SDLK_F6; - break; - case SDLK_7: - temporal_io=SDLK_F7; - break; - case SDLK_8: - temporal_io=SDLK_F8; - break; - case SDLK_9: - temporal_io=SDLK_F9; - break; - case SDLK_0: - temporal_io=SDLK_F10; - break; - case SDLK_o: - temporal_io=SDLK_F11; - break; - case SDLK_p: - temporal_io=SDLK_F12; - break; - } - } - - - if (pevento->type == SDL_KEYUP) - switch (temporal_io) { - case SDLK_ESCAPE: // to exit from the emulator - if (ordenador.esc_again==0) { - ordenador.esc_again=1; - strcpy(ordenador.osd_text,"ESC again to exit"); - ordenador.osd_time=100; - } else - salir = 0; - return; - break; - case SDLK_F1: - help_menu (); // shows the help menu - break; - - case SDLK_F2: - case SDLK_F3: - case SDLK_F4: - case SDLK_F7: - case SDLK_F8: - launch_menu(temporal_io); - break; - - case SDLK_F5: // STOP tape - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) - ordenador.pause = 1; - break; - - case SDLK_F6: // PLAY tape - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) - ordenador.pause = 0; - break; - - case SDLK_F9: - //SDL_Fullscreen_Switch(); - //Emulate load "" - - ordenador.keyboard_buffer[9].key.keysym.sym=SDLK_j; - ordenador.keyboard_buffer[9].type=SDL_KEYDOWN; - - ordenador.keyboard_buffer[8].key.keysym.sym=SDLK_j; - ordenador.keyboard_buffer[8].type=SDL_KEYUP; - - ordenador.keyboard_buffer[7].key.keysym.sym=SDLK_RCTRL; - ordenador.keyboard_buffer[7].type=SDL_KEYDOWN; - - ordenador.keyboard_buffer[6].key.keysym.sym=SDLK_p; - ordenador.keyboard_buffer[6].type=SDL_KEYDOWN; - - ordenador.keyboard_buffer[5].key.keysym.sym=SDLK_p; - ordenador.keyboard_buffer[5].type=SDL_KEYUP; - - ordenador.keyboard_buffer[4].key.keysym.sym=SDLK_p; - ordenador.keyboard_buffer[4].type=SDL_KEYDOWN; - - ordenador.keyboard_buffer[3].key.keysym.sym=SDLK_p; - ordenador.keyboard_buffer[3].type=SDL_KEYUP; - - ordenador.keyboard_buffer[2].key.keysym.sym=SDLK_RCTRL; - ordenador.keyboard_buffer[2].type=SDL_KEYUP; - - ordenador.keyboard_buffer[1].key.keysym.sym=SDLK_RETURN; - ordenador.keyboard_buffer[1].type=SDL_KEYDOWN; - - ordenador.keyboard_buffer[0].key.keysym.sym=SDLK_RETURN; - ordenador.keyboard_buffer[0].type=SDL_KEYUP; - - - ordenador.kbd_buffer_pointer=11; - countdown=5; - - break; - - case SDLK_F10: // Reset emulator - ResetComputer (); - ordenador.pause = 1; - if (ordenador.tap_file != NULL) { - ordenador.tape_current_mode = TAP_TRASH; - rewind_tape (ordenador.tap_file,1); - } - break; - - case SDLK_F11: // lower volume - if (ordenador.volume > 3) - set_volume (ordenador.volume - 4); - sprintf (ordenador.osd_text, " Volume: %d ",ordenador.volume / 4); - ordenador.osd_time = 50; - break; - - case SDLK_F12: // upper volume - set_volume (ordenador.volume + 4); - sprintf (ordenador.osd_text, " Volume: %d ",ordenador.volume / 4); - ordenador.osd_time = 50; - break; - } - - // reorder joystick if screen is rotated - - if(ordenador.zaurus_mini==2) { - switch(temporal_io) { - case SDLK_UP: - temporal_io=SDLK_LEFT; - break; - case SDLK_LEFT: - temporal_io=SDLK_DOWN; - break; - case SDLK_DOWN: - temporal_io=SDLK_RIGHT; - break; - case SDLK_RIGHT: - temporal_io=SDLK_UP; - break; - } - } - - - // test for joystick - - switch (temporal_io) { - case SDLK_UP: - switch (ordenador.joystick) { - case 0: // cursor - temporal_io = SDLK_7; - break; - - case 1: - ordenador.jk = 8; - break; - - case 2: // sinclair 1 - temporal_io = SDLK_4; - break; - - case 3: // sinclair 2 - temporal_io = SDLK_9; - break; - } - break; - - case SDLK_DOWN: - switch (ordenador.joystick) { - case 0: // cursor - temporal_io = SDLK_6; - break; - - case 1: - ordenador.jk = 4; - break; - - case 2: // sinclair 1 - temporal_io = SDLK_3; - break; - - case 3: // sinclair 2 - temporal_io = SDLK_8; - break; - } - break; - - case SDLK_RIGHT: - switch (ordenador.joystick) { - case 0: // cursor - temporal_io = SDLK_8; - break; - - case 1: - ordenador.jk = 1; - break; - - case 2: // sinclair 1 - temporal_io = SDLK_2; - break; - - case 3: // sinclair 2 - temporal_io = SDLK_7; - break; - - } - break; - - case SDLK_LEFT: - switch (ordenador.joystick) { - case 0: // cursor - temporal_io = SDLK_5; - break; - - case 1: - ordenador.jk = 2; - break; - - case 2: // sinclair 1 - temporal_io = SDLK_1; - break; - - case 3: // sinclair 2 - temporal_io = SDLK_6; - break; - } - break; - - case SDLK_RALT: - case SDLK_RMETA: - case SDLK_LMETA: - case SDLK_RSUPER: - case SDLK_LSUPER: - case SDLK_MENU: - switch (ordenador.joystick) { - case 0: // cursor - temporal_io = SDLK_0; - break; - - case 1: - ordenador.jk = 16; - break; - - case 2: // sinclair 1 - temporal_io = SDLK_5; - break; - - case 3: // sinclair 2 - temporal_io = SDLK_0; - break; - } - break; - } - - switch (temporal_io) { - - case SDLK_SPACE: - ordenador.k15 = 1; - break; - - case SDLK_RCTRL: - case SDLK_LCTRL: - ordenador.k15 = 2; - break; - - case SDLK_m: - ordenador.k15 = 4; - break; - - case SDLK_n: - ordenador.k15 = 8; - break; - - case SDLK_b: - ordenador.k15 = 16; - break; - - case SDLK_RETURN: - ordenador.k14 = 1; - break; - - case SDLK_l: - ordenador.k14 = 2; - break; - - case SDLK_k: - ordenador.k14 = 4; - break; - - case SDLK_j: - ordenador.k14 = 8; - break; - - case SDLK_h: - ordenador.k14 = 16; - break; - - case SDLK_p: - ordenador.k13 = 1; - break; - - case SDLK_o: - ordenador.k13 = 2; - break; - - case SDLK_i: - ordenador.k13 = 4; - break; - - case SDLK_u: - ordenador.k13 = 8; - break; - - case SDLK_y: - ordenador.k13 = 16; - break; - - case SDLK_0: - ordenador.k12 = 1; - break; - - case SDLK_9: - ordenador.k12 = 2; - break; - - case SDLK_8: - ordenador.k12 = 4; - break; - - case SDLK_7: - ordenador.k12 = 8; - break; - - case SDLK_6: - ordenador.k12 = 16; - break; - - case SDLK_1: - ordenador.k11 = 1; - break; - - case SDLK_2: - ordenador.k11 = 2; - break; - - case SDLK_3: - ordenador.k11 = 4; - break; - - case SDLK_4: - ordenador.k11 = 8; - break; - - case SDLK_5: - ordenador.k11 = 16; - break; - - case SDLK_q: - ordenador.k10 = 1; - break; - - case SDLK_w: - ordenador.k10 = 2; - break; - - case SDLK_e: - ordenador.k10 = 4; - break; - - case SDLK_r: - ordenador.k10 = 8; - break; - - case SDLK_t: - ordenador.k10 = 16; - break; - - case SDLK_a: - ordenador.k9 = 1; - break; - - case SDLK_s: - ordenador.k9 = 2; - break; - - case SDLK_d: - ordenador.k9 = 4; - break; - - case SDLK_f: - ordenador.k9 = 8; - break; - - case SDLK_g: - ordenador.k9 = 16; - break; - - case SDLK_RSHIFT: - case SDLK_LSHIFT: - ordenador.k8 = 1; - break; - - case SDLK_z: - ordenador.k8 = 2; - break; - - case SDLK_x: - ordenador.k8 = 4; - break; - - case SDLK_c: - ordenador.k8 = 8; - break; - - case SDLK_v: - ordenador.k8 = 16; - break; - - case SDLK_BACKSPACE: - ordenador.k12 = 1; - ordenador.k8 = 1; - break; - case SDLK_PERIOD: - ordenador.k15 = 6; - break; - case SDLK_COMMA: - ordenador.k15 = 10; - break; - - } - - if (pevento->type == SDL_KEYUP) { - ordenador.s8 |= ordenador.k8; - ordenador.s9 |= ordenador.k9; - ordenador.s10 |= ordenador.k10; - ordenador.s11 |= ordenador.k11; - ordenador.s12 |= ordenador.k12; - ordenador.s13 |= ordenador.k13; - ordenador.s14 |= ordenador.k14; - ordenador.s15 |= ordenador.k15; - ordenador.js &= (ordenador.jk ^ 255); - } else { - ordenador.s8 &= (ordenador.k8 ^ 255); - ordenador.s9 &= (ordenador.k9 ^ 255); - ordenador.s10 &= (ordenador.k10 ^ 255); - ordenador.s11 &= (ordenador.k11 ^ 255); - ordenador.s12 &= (ordenador.k12 ^ 255); - ordenador.s13 &= (ordenador.k13 ^ 255); - ordenador.s14 &= (ordenador.k14 ^ 255); - ordenador.s15 &= (ordenador.k15 ^ 255); - ordenador.js |= ordenador.jk; - } - - return; -} - -// resets the computer and loads the right ROMs - -void ResetComputer () { - - static int bucle; - - Z80free_reset (&procesador); - load_rom (ordenador.mode128k); - - // reset the AY-3-8912 - - for (bucle = 0; bucle < 16; bucle++) - ordenador.ay_registers[bucle] = 0; - - ordenador.aych_a = 0; - ordenador.aych_b = 0; - ordenador.aych_c = 0; - ordenador.aych_n = 0; - ordenador.aych_envel = 0; - ordenador.vol_a = 0; - ordenador.vol_b = 0; - ordenador.vol_c = 0; - - ordenador.s8|=0x1F; - ordenador.s9|=0x1F; - ordenador.s10|=0x1F; - ordenador.s11|=0x1F; - ordenador.s12|=0x1F; - ordenador.s13|=0x1F; - ordenador.s14|=0x1F; - ordenador.s15|=0x1F; - ordenador.js=0; - - ordenador.updown=0; - ordenador.leftright=0; - - ordenador.ulaplus=0; - - ordenador.mport1 = 0; - ordenador.mport2 = 0; - ordenador.video_offset = 0; // video in page 9 (page 5 in 128K) - switch (ordenador.mode128k) { - case 0: // 48K - ordenador.pixancho = 447; - ordenador.pixalto = 311; - - ordenador.block0 = ordenador.memoria; - ordenador.block1 = ordenador.memoria + 131072; // video mem. in page 9 (page 5 in 128K) - ordenador.block2 = ordenador.memoria + 65536; // 2nd block in page 6 (page 2 in 128K) - ordenador.block3 = ordenador.memoria + 65536; // 3rd block in page 7 (page 3 in 128K) - ordenador.mport1 = 32; // access to port 7FFD disabled - break; - - case 3: // +2A/+3 - Z80free_Out (0x1FFD, 0); - case 1: // 128K - case 2: // +2 - case 4: // spanish 128K - Z80free_Out (0x7FFD, 0); - ordenador.pixancho = 455; - ordenador.pixalto = 310; - break; - } - - microdrive_reset(); -} - -// check if there's contention and waits the right number of tstates - -void do_contention() { - - if (!ordenador.contended_zone) - return; - - if (ordenador.cicles_counter<14335) { - return; - } - - int ccicles=(ordenador.cicles_counter-14335)%8; - - if (ccicles>5) { - return; - } - - emulate(6-ccicles); - -} - -void Z80free_Wr (register word Addr, register byte Value) { - - switch (Addr & 0xC000) { - case 0x0000: - // only writes in the first 16K if we are in +3 mode and bit0 of mport2 is 1 - - if ((ordenador.mode128k == 3) && (1 == (ordenador.mport2 & 0x01))) - *(ordenador.block0 + Addr) = (unsigned char) Value; - break; - - case 0x4000: - do_contention(); - *(ordenador.block1 + Addr) = (unsigned char) Value; - break; - - case 0x8000: - *(ordenador.block2 + Addr) = (unsigned char) Value; - break; - - case 0xC000: - *(ordenador.block3 + Addr) = (unsigned char) Value; - break; - } -} - - -byte Z80free_Rd (register word Addr) { - - if((ordenador.mdr_active)&&(ordenador.mdr_paged)&&(Addr<8192)) // Interface I - return((byte)ordenador.shadowrom[Addr]); - - switch (ordenador.other_ret) { - case 1: - ordenador.other_ret = 0; - return (201); // RET instruction - break; - - default: - switch (Addr & 0xC000) { - case 0x0000: - return ((byte) (*(ordenador.block0 + Addr))); - break; - - case 0x4000: - do_contention(); - return ((byte) (*(ordenador.block1 + Addr))); - break; - - case 0x8000: - return ((byte) (*(ordenador.block2 + Addr))); - break; - - case 0xC000: - return ((byte) (*(ordenador.block3 + Addr))); - break; - - default: - printf ("Memory error\n"); - exit (1); - return 0; - } - break; - } -} - -void set_palete_entry(unsigned char entry, byte Value) { - - - SDL_Color color; - - color.r = ((Value<<3)&0xE0)+((Value)&0x1C)+((Value>>3)&0x03); - color.g = (Value&0xE0)+((Value>>3)&0x1C)+((Value>>6)&0x03); - color.b = ((Value<<6)&0xC0)+((Value<<4)&0x30)+((Value<<2)&0x0C)+((Value)&0x03); - - if (ordenador.bw!=0) { - int final; - final=(((int)color.r)*3+((int)color.g)*6+((int)color.b))/10; - color.r=color.g=color.b=(unsigned char)final; - } - // Color mode - - SDL_SetColors (ordenador.screen, &color, 32+entry, 1); // set 16 colors from the 16th - - if (ordenador.bpp!=1) { - colors[entry+16]=SDL_MapRGB(screen->format,color.r,color.g,color.b); - } -} - -void Z80free_Out (register word Port, register byte Value) { - - // Microdrive access - - register word maskport; - - if (((Port&0x0001)==0)||((Port>=0x4000)&&(Port<0x8000))) { - do_contention(); - } - - // ULAPlus - if (Port == 0xBF3B) { - ordenador.ulaplus_reg = Value; - return; - } - if (Port == 0xFF3B) { - if (ordenador.ulaplus_reg==0x40) { // mode - ordenador.ulaplus=Value&0x01; - return; - } - if (ordenador.ulaplus_reg<0x40) { // register set mode - ordenador.ulaplus_palete[ordenador.ulaplus_reg]=Value; - set_palete_entry(ordenador.ulaplus_reg,Value); - } - } - - if(((Port &0x0018)!=0x0018)&&(ordenador.mdr_active)) - microdrive_out(Port,Value); - - // ULA port (A0 low) - - if (!(Port & 0x0001)) { - ordenador.port254 = (unsigned char) Value; - ordenador.border = (((unsigned char) Value) & 0x07); - - if (ordenador.pause) { - if (Value & 0x10) - ordenador.sound_bit = 1; - else - ordenador.sound_bit = 0; // assign to SOUND_BIT the value - } - } - - // Memory page (7FFD & 1FFD) - - if (ordenador.mode128k==3) { - maskport=0x0FFD; - } else { - maskport=0x3FFD; - } - - if (((Port|maskport) == 0x7FFD) && (0 == (ordenador.mport1 & 0x20))) { - ordenador.mport1 = (unsigned char) Value; - set_memory_pointers (); // set the pointers - } - - if (((Port|maskport) == 0x1FFD) && (0 == (ordenador.mport1 & 0x20))) { - ordenador.mport2 = (unsigned char) Value; - set_memory_pointers (); // set the pointers - } - - // Sound chip (AY-3-8912) - - if (((Port|maskport) == 0xFFFD)&&(ordenador.ay_emul)) - ordenador.ay_latch = ((unsigned int) (Value & 0x0F)); - - if (((Port|maskport) == 0xBFFD)&&(ordenador.ay_emul)) { - ordenador.ay_registers[ordenador.ay_latch] = (unsigned char) Value; - if (ordenador.ay_latch == 13) - ordenador.ay_envel_way = 2; // start cycle - } -} - - -byte Z80free_In (register word Port) { - - static unsigned int temporal_io; - byte pines; - - if (((Port&0x0001)==0)||((Port>=0x4000)&&(Port<0x8000))) { - do_contention(); - } - - temporal_io = (unsigned int) Port; - - if (Port == 0xFF3B) { - if (ordenador.ulaplus_reg==0x40) { // mode - return(ordenador.ulaplus&0x01); - } - if (ordenador.ulaplus_reg<0x40) { // register set mode - return(ordenador.ulaplus_palete[ordenador.ulaplus_reg]); - } - } - - if (!(temporal_io & 0x0001)) { - pines = 0xBF; // by default, sound bit is 0 - if (!(temporal_io & 0x0100)) - pines &= ordenador.s8; - if (!(temporal_io & 0x0200)) - pines &= ordenador.s9; - if (!(temporal_io & 0x0400)) - pines &= ordenador.s10; - if (!(temporal_io & 0x0800)) - pines &= ordenador.s11; - if (!(temporal_io & 0x1000)) - pines &= ordenador.s12; - if (!(temporal_io & 0x2000)) - pines &= ordenador.s13; - if (!(temporal_io & 0x4000)) - pines &= ordenador.s14; - if (!(temporal_io & 0x8000)) - pines &= ordenador.s15; - - if (ordenador.pause) { - if (ordenador.issue == 2) { - if (ordenador.port254 & 0x18) - pines |= 0x40; - } else { - if (ordenador.port254 & 0x10) - pines |= 0x40; - } - } else { - if (ordenador.tape_readed) - pines |= 0x40; // sound input - else - pines &= 0xBF; // sound input - } - return (pines); - } - - // Joystick - if (!(temporal_io & 0x0020)) { - if (ordenador.joystick == 1) { - return (ordenador.js); - } else { - return 0; // if Kempston is not selected, emulate it, but always 0 - } - } - - if ((temporal_io == 0xFFFD)&&(ordenador.ay_emul)) - return (ordenador.ay_registers[ordenador.ay_latch]); - - // Microdrive access - - if(((Port &0x0018)!=0x0018)&&(ordenador.mdr_active)) - return(microdrive_in(Port)); - - pines=bus_empty(); - - return (pines); -} - -void set_volume (unsigned char volume) { - - unsigned char vol2; - int bucle; - - if (volume > 64) - vol2 = 64; - else - vol2 = volume; - - ordenador.volume = vol2; - - for (bucle = 0; bucle < 4; bucle++) { - ordenador.sample0[bucle] = 0; - ordenador.sample1[bucle] = 0; - ordenador.sample1b[bucle] = 0; - } - - switch (ordenador.format) { - case 0: // 8 bits/sample - ordenador.sample1[0] = 1 * vol2; - ordenador.sample1[1] = 1 * vol2; - ordenador.sample1b[0] = 1; - ordenador.sample1b[1] = 1; - break; - case 1: // 16 bits/sample, Little Endian - ordenador.sample1[0] = 1 * vol2; - ordenador.sample1[1] = 1 * vol2; - ordenador.sample1[2] = 1 * vol2; - ordenador.sample1[3] = 1 * vol2; - ordenador.sample1b[0] = 1; - ordenador.sample1b[1] = 1; - ordenador.sample1b[2] = 1; - ordenador.sample1b[3] = 1; - break; - case 2: // 16 bits/sample, Big Endian - ordenador.sample1[0] = 1 * vol2; - ordenador.sample1[1] = 1 * vol2; - ordenador.sample1[2] = 1 * vol2; - ordenador.sample1[3] = 1 * vol2; - ordenador.sample1b[0] = 1; - ordenador.sample1b[1] = 1; - ordenador.sample1b[2] = 1; - ordenador.sample1b[3] = 1; - break; - } -} +/* + * Copyright 2003-2009 (C) Raster Software Vigo (Sergio Costas) + * This file is part of FBZX + * + * FBZX 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 3 of the License, or + * (at your option) any later version. + * + * FBZX 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, see . + * + */ + +#include "z80free/Z80free.h" +#include "computer.h" +#include "emulator.h" +#include "menus.h" +#include "characters.h" +#include "sound.h" +#include +#include +#include +#include +#include +#include "tape.h" +#include "microdrive.h" + +#ifdef DEBUG +extern FILE *fdebug; +#define printf(...) fprintf(fdebug,__VA_ARGS__) +#else + #ifdef GEKKO + #define printf(...) + #endif +#endif + +/* Returns the bus value when reading a port without a periferial */ + +inline byte bus_empty () { + + if (ordenador.mode128k != 3) + return (ordenador.bus_value); + else + return (255); // +2A and +3 returns always 255 +} + +/* calls all the routines that emulates the computer, runing them for 'tstados' + tstates */ + +inline void emulate (int tstados) { + + if((procesador.I>=0x40)&&(procesador.I<=0x7F)) { + ordenador.screen_snow=1; + } else + ordenador.screen_snow=0; + show_screen (tstados); + play_ay (tstados); + play_sound (tstados); + tape_read (ordenador.tap_file, tstados); + microdrive_emulate(tstados); + if (!ordenador.pause) { + if (ordenador.tape_readed) + ordenador.sound_bit = 1; + else + ordenador.sound_bit = 0; // if not paused, asign SOUND_BIT the value of tape + } +} + +void computer_init () { + + int bucle; + + ordenador.bus_counter = 0; + ordenador.port254 = 0; + ordenador.issue = 3; + ordenador.mode128k = 0; + ordenador.joystick = 0; + + ordenador.tape_readed = 0; + ordenador.pause = 1; // tape stop + ordenador.tape_fast_load = 1; // fast load by default + ordenador.tape_current_mode = TAP_TRASH; + ordenador.tap_file = NULL; + + ordenador.osd_text[0] = 0; + ordenador.osd_time = 0; + + ordenador.other_ret = 0; + + ordenador.s8 = ordenador.s9 = ordenador.s10 = ordenador.s11 = + ordenador.s12 = ordenador.s13 = ordenador.s14 = + ordenador.s15 = 0xFF; + ordenador.tab_extended=0; + ordenador.esc_again=0; + + ordenador.js = 0x00; + + for (bucle = 0; bucle < 16; bucle++) + ordenador.ay_registers[bucle] = 0; + ordenador.ay_emul = 0; + ordenador.aych_a = 0; + ordenador.aych_b = 0; + ordenador.aych_c = 0; + ordenador.aych_n = 0; + ordenador.aych_envel = 0; + ordenador.vol_a = 0; + ordenador.vol_b = 0; + ordenador.vol_c = 0; + ordenador.tst_ay = 0; + ordenador.tst_ay2 = 0; + + ordenador.ayval_a = 0; + ordenador.ayval_b = 0; + ordenador.ayval_c = 0; + ordenador.ayval_n = 0; + ordenador.ay_envel_value = 0; + ordenador.ay_envel_way = 0; + + ordenador.tape_loop_counter = 0; + ordenador.kbd_buffer_pointer = 0; + ordenador.key = SDL_GetKeyState(NULL); +} + +void computer_set_palete() { + + SDL_Color colores[16]; + + if (ordenador.bw==0) { + // Color mode + + colores[0].r = 0; + colores[0].g = 0; + colores[0].b = 0; + colores[1].r = 0; + colores[1].g = 0; + colores[1].b = 192; + colores[2].r = 192; + colores[2].g = 0; + colores[2].b = 0; + colores[3].r = 192; + colores[3].g = 0; + colores[3].b = 192; + colores[4].r = 0; + colores[4].g = 192; + colores[4].b = 0; + colores[5].r = 0; + colores[5].g = 192; + colores[5].b = 192; + colores[6].r = 192; + colores[6].g = 192; + colores[6].b = 0; + colores[7].r = 192; + colores[7].g = 192; + colores[7].b = 192; + colores[8].r = 0; + colores[8].g = 0; + colores[8].b = 0; + colores[9].r = 0; + colores[9].g = 0; + colores[9].b = 255; + colores[10].r = 255; + colores[10].g = 0; + colores[10].b = 0; + colores[11].r = 255; + colores[11].g = 0; + colores[11].b = 255; + colores[12].r = 0; + colores[12].g = 255; + colores[12].b = 0; + colores[13].r = 0; + colores[13].g = 255; + colores[13].b = 255; + colores[14].r = 255; + colores[14].g = 255; + colores[14].b = 0; + colores[15].r = 255; + colores[15].g = 255; + colores[15].b = 255; + + SDL_SetColors (ordenador.screen, colores, 16, 16); // set 16 colors from the 16th + + if (ordenador.bpp!=1) { + colors[0]=SDL_MapRGB(screen->format,0,0,0); + colors[1]=SDL_MapRGB(screen->format,0,0,192); + colors[2]=SDL_MapRGB(screen->format,192,0,0); + colors[3]=SDL_MapRGB(screen->format,192,0,192); + colors[4]=SDL_MapRGB(screen->format,0,192,0); + colors[5]=SDL_MapRGB(screen->format,0,192,192); + colors[6]=SDL_MapRGB(screen->format,192,192,0); + colors[7]=SDL_MapRGB(screen->format,192,192,192); + colors[8]=SDL_MapRGB(screen->format,0,0,0); + colors[9]=SDL_MapRGB(screen->format,0,0,255); + colors[10]=SDL_MapRGB(screen->format,255,0,0); + colors[11]=SDL_MapRGB(screen->format,255,0,255); + colors[12]=SDL_MapRGB(screen->format,0,255,0); + colors[13]=SDL_MapRGB(screen->format,0,255,255); + colors[14]=SDL_MapRGB(screen->format,255,255,0); + colors[15]=SDL_MapRGB(screen->format,255,255,255); + } + } else { + + // B&W mode + + colores[0].r = 0; + colores[0].g = 0; + colores[0].b = 0; + + colores[1].r = 22; + colores[1].g = 22; + colores[1].b = 22; + + colores[2].r = 57; + colores[2].g = 57; + colores[2].b = 57; + + colores[3].r = 79; + colores[3].g = 79; + colores[3].b = 79; + + colores[4].r = 113; + colores[4].g = 113; + colores[4].b = 113; + + colores[5].r = 135; + colores[5].g = 135; + colores[5].b = 135; + + colores[6].r = 160; + colores[6].g = 160; + colores[6].b = 160; + + colores[7].r = 192; + colores[7].g = 192; + colores[7].b = 192; + + colores[8].r = 0; + colores[8].g = 0; + colores[8].b = 0; + + colores[9].r = 29; + colores[9].g = 29; + colores[9].b = 29; + + colores[10].r = 76; + colores[10].g = 76; + colores[10].b = 76; + + colores[11].r = 105; + colores[11].g = 105; + colores[11].b = 105; + + colores[12].r = 150; + colores[12].g = 150; + colores[12].b = 150; + + colores[13].r = 179; + colores[13].g = 179; + colores[13].b = 179; + + colores[14].r = 226; + colores[14].g = 226; + colores[14].b = 226; + + colores[15].r = 255; + colores[15].g = 255; + colores[15].b = 255; + + SDL_SetColors (ordenador.screen, colores, 16, 16); // set 16 colors from the 16th + + if (ordenador.bpp!=1) { + colors[0]=SDL_MapRGB(screen->format,0,0,0); + colors[1]=SDL_MapRGB(screen->format,22,22,22); + colors[2]=SDL_MapRGB(screen->format,57,57,57); + colors[3]=SDL_MapRGB(screen->format,79,79,79); + colors[4]=SDL_MapRGB(screen->format,113,113,113); + colors[5]=SDL_MapRGB(screen->format,135,135,135); + colors[6]=SDL_MapRGB(screen->format,160,160,160); + colors[7]=SDL_MapRGB(screen->format,192,192,192); + colors[8]=SDL_MapRGB(screen->format,0,0,0); + colors[9]=SDL_MapRGB(screen->format,29,29,29); + colors[10]=SDL_MapRGB(screen->format,76,76,76); + colors[11]=SDL_MapRGB(screen->format,105,105,105); + colors[12]=SDL_MapRGB(screen->format,150,150,150); + colors[13]=SDL_MapRGB(screen->format,179,179,179); + colors[14]=SDL_MapRGB(screen->format,226,226,226); + colors[15]=SDL_MapRGB(screen->format,255,255,255); + } + } + + unsigned int c; + + for(c=0x10;c<60;c++) { + colors[c]=0x00000000; + } + + if (ordenador.bpp==1) { + unsigned int v; + for (c=0x10;c<0x60;c++) { + v=c+((c<<8)&0x0000FF00)+((c<<16)&0x00FF0000)+((c<<24)&0xFF000000); + colors[c-0x10]=v; + } + } + for(c=0;c<64;c++) { + set_palete_entry((unsigned char)c,ordenador.ulaplus_palete[c]); + } +} + +/* Registers the screen surface where the Spectrum will put the picture, +prepares the palette and creates two arrays (translate and translate2) +that gives the memory address for each scan */ + +void register_screen (SDL_Surface * pantalla) { + + //int resx,resy; + int bucle, bucle2, bucle3, bucle4, bucle5; + + // we prepare the scanline transform arrays + + bucle5 = 0; + for (bucle = 0; bucle < 3; bucle++) + for (bucle2 = 0; bucle2 < 8; bucle2++) + for (bucle3 = 0; bucle3 < 8; bucle3++) + for (bucle4 = 0; bucle4 < 32; bucle4++) { + ordenador.translate[bucle5] = + 147456 + bucle * 2048 + + bucle2 * 32 + bucle3 * 256 + + bucle4; + ordenador.translate2[bucle5] = + 153600 + bucle * 256 + + bucle2 * 32 + bucle4; + bucle5++; + } + ordenador.tstados_counter = 0; + + ordenador.screen = pantalla; + + ordenador.border = 0; + ordenador.currline = 0; + ordenador.currpix = 0; + ordenador.flash = 0; + + //resx = ordenador.screen->w; + //resy = ordenador.screen->h; + + switch (ordenador.zaurus_mini) { + case 0: + ordenador.init_line = 0; + ordenador.next_line = 640; + ordenador.next_scanline = 640; + ordenador.first_line = 40; + ordenador.last_line = 280; + ordenador.first_pixel = 16; + ordenador.last_pixel = 336; + ordenador.next_pixel = 1; + ordenador.jump_pixel = 16; + break; + case 1: + ordenador.init_line = 65; + ordenador.next_line = 160; + ordenador.next_scanline = 160; + ordenador.first_line = 40; + ordenador.last_line = 280; + ordenador.first_pixel = 0; + ordenador.last_pixel = 351; + ordenador.next_pixel = 1; + ordenador.jump_pixel = 8; + break; + case 2: + ordenador.init_line = 479; + ordenador.next_line = -(307202); + ordenador.next_scanline = -1; + ordenador.first_line = 40; + ordenador.last_line = 280; + ordenador.first_pixel = 16; + ordenador.last_pixel = 336; + ordenador.next_pixel = 480; + ordenador.jump_pixel = 7680; + break; + case 3: + ordenador.init_line = 0; + ordenador.next_line = 0; + ordenador.next_scanline = 0; + ordenador.first_line = 40; + ordenador.last_line = 280; + ordenador.first_pixel = 0; + ordenador.last_pixel = 319; + ordenador.next_pixel = 1; + ordenador.jump_pixel = 4; + break; + } + + ordenador.next_line*=ordenador.bpp; + ordenador.next_scanline*=ordenador.bpp; + ordenador.init_line*=ordenador.bpp; + ordenador.next_pixel*=ordenador.bpp; + ordenador.jump_pixel*=ordenador.bpp; + + computer_set_palete(); + + ordenador.pixel = ((unsigned char *) (ordenador.screen->pixels)) + ordenador.init_line; + ordenador.interr = 0; + + ordenador.p_translt = ordenador.translate; + ordenador.p_translt2 = ordenador.translate2; + + ordenador.contador_flash = 0; + ordenador.readed = 0; + + ordenador.contended_zone=0; + ordenador.cicles_counter=0; + + ordenador.tstados_counter_sound = 0; + ordenador.current_buffer = sound[0]; + ordenador.num_buff = 0; // first buffer + ordenador.sound_cuantity = 0; + ordenador.sound_current_value = 0; + ordenador.pixancho = 447; + ordenador.pixalto = 311; // values for 48K mode +} + +void set_memory_pointers () { + + static unsigned int rom, ram; + + // assign the offset for video page + + if (ordenador.mport1 & 0x08) + ordenador.video_offset = 32768; // page 7 + else + ordenador.video_offset = 0; // page 5 + + // assign ROMs and, if in special mode, RAM for the whole blocks + + if ((ordenador.mode128k == 3)) { + if (ordenador.mport2 & 0x01) { // +2A/+3 special mode + ram = (unsigned int) (ordenador.mport1 & 0x06); // bits 1&2 + switch (ram) { + case 0: + ordenador.block0 = ordenador.memoria + 65536; + ordenador.block1 = ordenador.memoria + 65536; + ordenador.block2 = ordenador.memoria + 65536; + ordenador.block3 = ordenador.memoria + 65536; + break; + case 2: + ordenador.block0 = ordenador.memoria + 131072; + ordenador.block1 = ordenador.memoria + 131072; + ordenador.block2 = ordenador.memoria + 131072; + ordenador.block3 = ordenador.memoria + 131072; + break; + case 4: + ordenador.block0 = ordenador.memoria + 131072; + ordenador.block1 = ordenador.memoria + 131072; + ordenador.block2 = ordenador.memoria + 131072; + ordenador.block3 = ordenador.memoria + 65536; + break; + case 6: + ordenador.block0 = ordenador.memoria + 131072; + ordenador.block1 = ordenador.memoria + 163840; + ordenador.block2 = ordenador.memoria + 131072; + ordenador.block3 = ordenador.memoria + 65536; + break; + } + return; + } else { // ROMs for +2A/+3 normal mode + rom = 0; + if (ordenador.mport1 & 0x10) + rom++; + if (ordenador.mport2 & 0x04) + rom += 2; + // assign the first block pointer to the right block bank + ordenador.block0 = ordenador.memoria + (16384 * rom); + } + } else { // ROMs for 128K/+2 mode + if (ordenador.mport1 & 0x10) + ordenador.block0 = ordenador.memoria + 16384; + else + ordenador.block0 = ordenador.memoria; + } + + // RAMs for 128K/+2 mode, and +2A/+3 in normal mode + + ordenador.block1 = ordenador.memoria + 131072; // page 5 minus 16384 + ordenador.block2 = ordenador.memoria + 65536; // page 2 minus 32768 + + ram = 1 + ((unsigned int) (ordenador.mport1 & 0x07)); // RAM page for block3 plus 1 + ordenador.block3 = ordenador.memoria + (16384 * ram); // page n minus 49152 +} + +/* Paints the spectrum screen during the TSTADOS tstates that the Z80 used +to execute last instruction */ + +inline void show_screen (int tstados) { + + static unsigned char temporal, ink, paper, fflash, tmp2; + + ordenador.tstados_counter += tstados; + ordenador.cicles_counter += tstados; + + if (curr_frames!=jump_frames) { + if (ordenador.tstados_counter>=69888) { + ordenador.tstados_counter-=69888; + ordenador.interr = 1; + curr_frames++; + } + return; + } + + fflash = 0; // flash flag + while (ordenador.tstados_counter > 3) { + ordenador.tstados_counter -= 4; + + // test if current pixel is for border or for user area + + if ((ordenador.currline < 64) || (ordenador.currline > 255) + || (ordenador.currpix < 48) || (ordenador.currpix > 303)) { + + // is border + + ordenador.contended_zone=0; // no contention here + if (ordenador.ulaplus) { + paint_pixels (255, ordenador.border+24, 0); // paint 8 pixels with BORDER color + } else { + paint_pixels (255, ordenador.border, 0); // paint 8 pixels with BORDER color + } + + ordenador.bus_value = 255; + + } else { + + // is user area. We search for ink and paper colours + + ordenador.contended_zone=1; // can have contention + + temporal = ordenador.memoria[(*ordenador.p_translt2) + ordenador.video_offset]; // attributes + ordenador.bus_value = temporal; + ink = temporal & 0x07; // ink colour + paper = (temporal >> 3) & 0x07; // paper colour + if (ordenador.ulaplus) { + tmp2=0x10+((temporal>>2)&0x30); + ink+=tmp2; + paper+=8+tmp2; + } else { + if (temporal & 0x40) { // bright flag? + ink += 8; + paper += 8; + } + fflash = temporal & 0x80; // flash flag + } + + // Snow Effect + + if(ordenador.screen_snow) { + temporal = ordenador.memoria[(((*ordenador.p_translt) + (ordenador.video_offset))&0xFFFFFF00)+(procesador.R)]; // data with snow + ordenador.screen_snow=0; // no more snow for now + } else + temporal = ordenador.memoria[(*ordenador.p_translt) + ordenador.video_offset]; // data + + ordenador.p_translt++; + ordenador.p_translt2++; + if ((fflash) && (ordenador.flash)) + paint_pixels (temporal, paper, ink); // if FLASH, invert PAPER and INK + else + paint_pixels (temporal, ink, paper); + } + ordenador.currpix += 8; + if (ordenador.currpix > ordenador.pixancho) { + ordenador.currpix = 0; + ordenador.currline++; + if (ordenador.currline > ordenador.first_line) { // ordenador.first_line) + ordenador.pixel += ordenador.next_line; // ordenador.next_line; + } + } + + if ((ordenador.currline > ordenador.pixalto)&&(ordenador.currpix>=64)) { + ordenador.currpix=64; + if (ordenador.osd_time) { + ordenador.osd_time--; + if (ordenador.osd_time==0) { + ordenador.tab_extended=0; + ordenador.esc_again=0; + } + + if (ordenador.osd_time) + print_string (ordenador.screenbuffer,ordenador.osd_text, -1,450, 12, 0,ordenador.screen_width); + else { + if (ordenador.zaurus_mini==0) + print_string (ordenador.screenbuffer," ",-1, 450, 12, 0,ordenador.screen_width); + else + print_string (ordenador.screenbuffer," ",-1, 450, 12, 0,ordenador.screen_width); + } + } + + if (ordenador.mustlock) { + SDL_UnlockSurface (ordenador.screen); + SDL_Flip (ordenador.screen); + SDL_LockSurface (ordenador.screen); + } else { + SDL_Flip (ordenador.screen); + } + + curr_frames=0; + ordenador.currline = 0; + ordenador.interr = 1; + ordenador.cicles_counter=0; + ordenador.pixel = ((unsigned char *) (ordenador.screen->pixels))+ordenador.init_line; // +ordenador.init_line; + ordenador.p_translt = ordenador.translate; + ordenador.p_translt2 = ordenador.translate2; + ordenador.contador_flash++; + if (ordenador.contador_flash == 16) { + ordenador.flash = 1 - ordenador.flash; + ordenador.contador_flash = 0; + } + } + } +} + + +/* PAINT_PIXELS paints one byte with INK color for 1 bits and PAPER color +for 0 bits, and increment acordingly the pointer PIXEL */ + +inline void paint_pixels (unsigned char octet,unsigned char ink, unsigned char paper) { + + static int bucle,valor,*p; + static unsigned char mask; + + if ((ordenador.currpix < 16) || (ordenador.currpix >= 336) + || (ordenador.currline < 40) || (ordenador.currline >= 280)) + return; + + mask = 0x80; + for (bucle = 0; bucle < 8; bucle++) { + valor = (octet & mask) ? (int) ink : (int) paper; + p=(colors+valor); + + paint_one_pixel((unsigned char *)p,ordenador.pixel); + if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3)&&(ordenador.dblscan)) { + paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline); + } + ordenador.pixel+=ordenador.next_pixel; + if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3)) { + paint_one_pixel((unsigned char *)p,ordenador.pixel); + if (ordenador.dblscan) { + paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline); + } + ordenador.pixel+=ordenador.next_pixel; + } + mask = ((mask >> 1) & 0x7F); + } +} + +inline void paint_one_pixel(unsigned char *colour,unsigned char *address) { + + #if BYTE_ORDER == LITTLE_ENDIAN + switch(ordenador.bpp) { + case 1: + *address=*colour; + break; + case 3: + *(address++)=*(colour++); + case 2: + *(address++)=*(colour++); + *(address++)=*(colour++); + break; + case 4: + *((unsigned int *)address)=*((unsigned int *)colour); + break; + } + #else //BIG ENDIAN + switch(ordenador.bpp) { + case 1: + *address=*(colour+3); + break; + case 3: + *(address++)=*(colour+1); + case 2: + *(address++)=*(colour+2); + *(address++)=*(colour+3); + break; + case 4: + *((unsigned int *)address)=*((unsigned int *)colour); + break; + } + #endif + +} + +// Read the keyboard and stores the flags + +inline void read_keyboard () { + + unsigned int temporal_io; + SDL_Event evento,*pevento; + static int countdown; + enum joystate_x {JOY_CENTER_X, JOY_LEFT, JOY_RIGHT}; + enum joystate_y {JOY_CENTER_Y, JOY_UP, JOY_DOWN}; + int joy_axis_x,joy_axis_y, joy_fire; + + ordenador.k8 = ordenador.k9 = ordenador.k10 = ordenador.k11 = + ordenador.k12 = ordenador.k13 = ordenador.k14 = + ordenador.k15 = 0; + ordenador.jk = 0; + + if (ordenador.kbd_buffer_pointer) + { + if (countdown) + countdown--; + else + { + switch (ordenador.kbd_buffer_pointer) + { + case 6: //Edit + ordenador.k8|=1; + ordenador.k11|=1; + break; + case 5: //Load + ordenador.k14|= 8; + break; + case 4: //" + ordenador.k15|= 2; + ordenador.k13|= 1; + break; + case 3: //" + ordenador.k15|= 2; + ordenador.k13|= 1; + break; + case 2: // Return + ordenador.k14|= 1; + break; + case 1: + if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + ordenador.pause = 0; + break; + } + ordenador.kbd_buffer_pointer--; + countdown=5; + } + } + + pevento=&evento; + SDL_PollEvent (&evento); + + + if (pevento->type==SDL_QUIT) { + salir = 0; + return; + } + + SDL_JoystickUpdate(); + joy_axis_x = SDL_JoystickGetAxis(ordenador.joystick_sdl[0], 0); + joy_axis_y = SDL_JoystickGetAxis(ordenador.joystick_sdl[0], 1); + joy_fire = SDL_JoystickGetButton(ordenador.joystick_sdl[0], 0); //Wii button A + + if (SDL_JoystickGetButton(ordenador.joystick_sdl[0], 6)) help_menu (); + + if (joy_axis_x > 16384) ordenador.joy_axis_x_state[0] = JOY_RIGHT; + else if (joy_axis_x < -16384) ordenador.joy_axis_x_state[0] = JOY_LEFT; + else ordenador.joy_axis_x_state[0] = JOY_CENTER_X; + + if (joy_axis_y > 16384) ordenador.joy_axis_y_state[0] = JOY_DOWN; + else if (joy_axis_y < -16384) ordenador.joy_axis_y_state[0] = JOY_UP; + else ordenador.joy_axis_y_state[0] = JOY_CENTER_Y; + + temporal_io = (unsigned int) pevento->key.keysym.sym; + + /* + if ((pevento->type==SDL_KEYDOWN)&&(temporal_io==SDLK_TAB)) { + if (ordenador.tab_extended==0) { + ordenador.tab_extended=1; + strcpy(ordenador.osd_text,"Function Key mode on"); + ordenador.osd_time=100; + return; + } else { + ordenador.tab_extended=0; + ordenador.osd_time=0; + return; + } + } + + if ((pevento->type==SDL_KEYDOWN)&&(ordenador.tab_extended==1)) { + ordenador.tab_extended=0; + ordenador.osd_time=0; + switch(temporal_io) { + case SDLK_1: + temporal_io=SDLK_F1; + break; + case SDLK_2: + temporal_io=SDLK_F2; + break; + case SDLK_3: + temporal_io=SDLK_F3; + break; + case SDLK_4: + temporal_io=SDLK_F4; + break; + case SDLK_5: + temporal_io=SDLK_F5; + break; + case SDLK_6: + temporal_io=SDLK_F6; + break; + case SDLK_7: + temporal_io=SDLK_F7; + break; + case SDLK_8: + temporal_io=SDLK_F8; + break; + case SDLK_9: + temporal_io=SDLK_F9; + break; + case SDLK_0: + temporal_io=SDLK_F10; + break; + case SDLK_o: + temporal_io=SDLK_F11; + break; + case SDLK_p: + temporal_io=SDLK_F12; + break; + } + } + */ + if (pevento->type == SDL_KEYDOWN) + switch (temporal_io) { + case SDLK_ESCAPE: // to exit from the emulator + if (ordenador.esc_again==0) { + ordenador.esc_again=1; + strcpy(ordenador.osd_text,"ESC again to exit"); + ordenador.osd_time=100; + } else + salir = 0; + return; + break; + case SDLK_F1: + help_menu (); // shows the help menu + break; + + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F7: + case SDLK_F8: + launch_menu(temporal_io); + break; + + case SDLK_F5: // STOP tape + if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + ordenador.pause = 1; + break; + + case SDLK_F6: // PLAY tape + if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + ordenador.pause = 0; + break; + + case SDLK_F9: + //Emulate load "" + + ordenador.kbd_buffer_pointer=6; + countdown=5; + break; + + case SDLK_F10: // Reset emulator + ResetComputer (); + ordenador.pause = 1; + if (ordenador.tap_file != NULL) { + ordenador.tape_current_mode = TAP_TRASH; + rewind_tape (ordenador.tap_file,1); + } + break; + + case SDLK_F11: // lower volume + if (ordenador.volume > 3) + set_volume (ordenador.volume - 4); + sprintf (ordenador.osd_text, " Volume: %d ",ordenador.volume / 4); + ordenador.osd_time = 50; + break; + + case SDLK_F12: // upper volume + set_volume (ordenador.volume + 4); + sprintf (ordenador.osd_text, " Volume: %d ",ordenador.volume / 4); + ordenador.osd_time = 50; + break; + } + + // reorder joystick if screen is rotated + + if(ordenador.zaurus_mini==2) { + switch(temporal_io) { + case SDLK_UP: + temporal_io=SDLK_LEFT; + break; + case SDLK_LEFT: + temporal_io=SDLK_DOWN; + break; + case SDLK_DOWN: + temporal_io=SDLK_RIGHT; + break; + case SDLK_RIGHT: + temporal_io=SDLK_UP; + break; + } + } + + switch (ordenador.joystick) { + case 0: // cursor + if (ordenador.joy_axis_y_state[0] == JOY_UP) ordenador.k12|= 8; + if (ordenador.joy_axis_y_state[0] == JOY_DOWN) ordenador.k12|= 16; + if (ordenador.joy_axis_x_state[0] == JOY_RIGHT)ordenador.k12|= 4; + if (ordenador.joy_axis_x_state[0] == JOY_LEFT) ordenador.k11|= 16; + if (joy_fire) ordenador.k12|= 1; + break; + + case 1: //Kempston + if (ordenador.joy_axis_y_state[0] == JOY_UP) ordenador.jk|= 8; + if (ordenador.joy_axis_y_state[0] == JOY_DOWN) ordenador.jk|= 4; + if (ordenador.joy_axis_x_state[0] == JOY_RIGHT) ordenador.jk|= 1; + if (ordenador.joy_axis_x_state[0] == JOY_LEFT) ordenador.jk|= 2; + if (joy_fire) ordenador.jk = 16; + break; + + case 2: // sinclair 1 + if (ordenador.joy_axis_y_state[0] == JOY_UP) ordenador.k11|= 8; + if (ordenador.joy_axis_y_state[0] == JOY_DOWN)ordenador.k11|= 4; + if (ordenador.joy_axis_x_state[0] == JOY_RIGHT)ordenador.k11|= 2; + if (ordenador.joy_axis_x_state[0] == JOY_LEFT) ordenador.k11|= 1; + if (joy_fire) ordenador.k11|= 16; + break; + + case 3: // sinclair 2 + if (ordenador.joy_axis_y_state[0] == JOY_UP) ordenador.k12|= 2; + if (ordenador.joy_axis_y_state[0] == JOY_DOWN)ordenador.k12|= 4; + if (ordenador.joy_axis_x_state[0] == JOY_RIGHT)ordenador.k12|= 8; + if (ordenador.joy_axis_x_state[0] == JOY_LEFT) ordenador.k12|= 16; + if (joy_fire) ordenador.k12|= 1; + break; + } + + if (ordenador.key[SDLK_SPACE]) ordenador.k15|=1; + if (ordenador.key[SDLK_RCTRL]) ordenador.k15|=2; + if (ordenador.key[SDLK_LCTRL]) ordenador.k15|=2; + if (ordenador.key[SDLK_m]) ordenador.k15|=4; + if (ordenador.key[SDLK_n]) ordenador.k15|=8; + if (ordenador.key[SDLK_b]) ordenador.k15|=16; + if (ordenador.key[SDLK_PERIOD]) ordenador.k15|=6; + if (ordenador.key[SDLK_COMMA]) ordenador.k15|=10; + + if (ordenador.key[SDLK_RETURN]) ordenador.k14|=1; + if (ordenador.key[SDLK_l]) ordenador.k14|=2; + if (ordenador.key[SDLK_k]) ordenador.k14|=4; + if (ordenador.key[SDLK_j]) ordenador.k14|=8; + if (ordenador.key[SDLK_h]) ordenador.k14|=16; + + if (ordenador.key[SDLK_p]) ordenador.k13|=1; + if (ordenador.key[SDLK_o]) ordenador.k13|=2; + if (ordenador.key[SDLK_i]) ordenador.k13|=4; + if (ordenador.key[SDLK_u]) ordenador.k13|=8; + if (ordenador.key[SDLK_y]) ordenador.k13|=16; + + if (ordenador.key[SDLK_0]) ordenador.k12|=1; + if (ordenador.key[SDLK_9]) ordenador.k12|=2; + if (ordenador.key[SDLK_8]) ordenador.k12|=4; + if (ordenador.key[SDLK_7]) ordenador.k12|=8; + if (ordenador.key[SDLK_6]) ordenador.k12|=16; + if (ordenador.key[SDLK_BACKSPACE]) {ordenador.k12|=1; ordenador.k8 |=1;} + + if (ordenador.key[SDLK_1]) ordenador.k11|=1; + if (ordenador.key[SDLK_2]) ordenador.k11|=2; + if (ordenador.key[SDLK_3]) ordenador.k11|=4; + if (ordenador.key[SDLK_4]) ordenador.k11|=8; + if (ordenador.key[SDLK_5]) ordenador.k11|=16; + + if (ordenador.key[SDLK_q]) ordenador.k10|=1; + if (ordenador.key[SDLK_w]) ordenador.k10|=2; + if (ordenador.key[SDLK_e]) ordenador.k10|=4; + if (ordenador.key[SDLK_r]) ordenador.k10|=8; + if (ordenador.key[SDLK_t]) ordenador.k10|=16; + + if (ordenador.key[SDLK_a]) ordenador.k9 |=1; + if (ordenador.key[SDLK_s]) ordenador.k9 |=2; + if (ordenador.key[SDLK_d]) ordenador.k9 |=4; + if (ordenador.key[SDLK_f]) ordenador.k9 |=8; + if (ordenador.key[SDLK_g]) ordenador.k9 |=16; + + if (ordenador.key[SDLK_RSHIFT]) ordenador.k8 |=1; + if (ordenador.key[SDLK_LSHIFT]) ordenador.k8 |=1; + if (ordenador.key[SDLK_z]) ordenador.k8 |=2; + if (ordenador.key[SDLK_x]) ordenador.k8 |=4; + if (ordenador.key[SDLK_c]) ordenador.k8 |=8; + if (ordenador.key[SDLK_v]) ordenador.k8 |=16; + + if (ordenador.key[SDLK_UP]) {ordenador.k12 |=8;ordenador.k8|=1;} + if (ordenador.key[SDLK_DOWN]) {ordenador.k12 |=16;ordenador.k8|=1;} + if (ordenador.key[SDLK_LEFT]) {ordenador.k11 |=16;ordenador.k8|=1;} + if (ordenador.key[SDLK_RIGHT]) {ordenador.k12 |=4;ordenador.k8|=1;} + + ordenador.s8 = (ordenador.s8 & 0xE0) | (ordenador.k8 ^ 0x1F); + ordenador.s9 = (ordenador.s9 & 0xE0) | (ordenador.k9 ^ 0x1F); + ordenador.s10 = (ordenador.s10 & 0xE0)| (ordenador.k10 ^ 0x1F); + ordenador.s11 = (ordenador.s11 & 0xE0)| (ordenador.k11 ^ 0x1F); + ordenador.s12 = (ordenador.s12 & 0xE0)| (ordenador.k12 ^ 0x1F); + ordenador.s13 = (ordenador.s13 & 0xE0)| (ordenador.k13 ^ 0x1F); + ordenador.s14 = (ordenador.s14 & 0xE0)| (ordenador.k14 ^ 0x1F); + ordenador.s15 = (ordenador.s15 & 0xE0)| (ordenador.k15 ^ 0x1F); + ordenador.js = ordenador.jk; + + return; +} + +// resets the computer and loads the right ROMs + +void ResetComputer () { + + static int bucle; + + Z80free_reset (&procesador); + load_rom (ordenador.mode128k); + + // reset the AY-3-8912 + + for (bucle = 0; bucle < 16; bucle++) + ordenador.ay_registers[bucle] = 0; + + ordenador.aych_a = 0; + ordenador.aych_b = 0; + ordenador.aych_c = 0; + ordenador.aych_n = 0; + ordenador.aych_envel = 0; + ordenador.vol_a = 0; + ordenador.vol_b = 0; + ordenador.vol_c = 0; + + ordenador.s8|=0x1F; + ordenador.s9|=0x1F; + ordenador.s10|=0x1F; + ordenador.s11|=0x1F; + ordenador.s12|=0x1F; + ordenador.s13|=0x1F; + ordenador.s14|=0x1F; + ordenador.s15|=0x1F; + ordenador.js=0; + + ordenador.updown=0; + ordenador.leftright=0; + + ordenador.ulaplus=0; + + ordenador.mport1 = 0; + ordenador.mport2 = 0; + ordenador.video_offset = 0; // video in page 9 (page 5 in 128K) + switch (ordenador.mode128k) { + case 0: // 48K + ordenador.pixancho = 447; + ordenador.pixalto = 311; + + ordenador.block0 = ordenador.memoria; + ordenador.block1 = ordenador.memoria + 131072; // video mem. in page 9 (page 5 in 128K) + ordenador.block2 = ordenador.memoria + 65536; // 2nd block in page 6 (page 2 in 128K) + ordenador.block3 = ordenador.memoria + 65536; // 3rd block in page 7 (page 3 in 128K) + ordenador.mport1 = 32; // access to port 7FFD disabled + break; + + case 3: // +2A/+3 + Z80free_Out (0x1FFD, 0); + case 1: // 128K + case 2: // +2 + case 4: // spanish 128K + Z80free_Out (0x7FFD, 0); + ordenador.pixancho = 455; + ordenador.pixalto = 310; + break; + } + + microdrive_reset(); +} + +// check if there's contention and waits the right number of tstates + +void do_contention() { + + if (!ordenador.contended_zone) + return; + + if (ordenador.cicles_counter<14335) { + return; + } + + int ccicles=(ordenador.cicles_counter-14335)%8; + + if (ccicles>5) { + return; + } + + emulate(6-ccicles); + +} + +void Z80free_Wr (register word Addr, register byte Value) { + + switch (Addr & 0xC000) { + case 0x0000: + // only writes in the first 16K if we are in +3 mode and bit0 of mport2 is 1 + + if ((ordenador.mode128k == 3) && (1 == (ordenador.mport2 & 0x01))) + *(ordenador.block0 + Addr) = (unsigned char) Value; + break; + + case 0x4000: + do_contention(); + *(ordenador.block1 + Addr) = (unsigned char) Value; + break; + + case 0x8000: + *(ordenador.block2 + Addr) = (unsigned char) Value; + break; + + case 0xC000: + *(ordenador.block3 + Addr) = (unsigned char) Value; + break; + } +} + + +byte Z80free_Rd (register word Addr) { + + if((ordenador.mdr_active)&&(ordenador.mdr_paged)&&(Addr<8192)) // Interface I + return((byte)ordenador.shadowrom[Addr]); + + switch (ordenador.other_ret) { + case 1: + ordenador.other_ret = 0; + return (201); // RET instruction + break; + + default: + switch (Addr & 0xC000) { + case 0x0000: + return ((byte) (*(ordenador.block0 + Addr))); + break; + + case 0x4000: + do_contention(); + return ((byte) (*(ordenador.block1 + Addr))); + break; + + case 0x8000: + return ((byte) (*(ordenador.block2 + Addr))); + break; + + case 0xC000: + return ((byte) (*(ordenador.block3 + Addr))); + break; + + default: + printf ("Memory error\n"); + exit (1); + return 0; + } + break; + } +} + +void set_palete_entry(unsigned char entry, byte Value) { + + + SDL_Color color; + + color.r = ((Value<<3)&0xE0)+((Value)&0x1C)+((Value>>3)&0x03); + color.g = (Value&0xE0)+((Value>>3)&0x1C)+((Value>>6)&0x03); + color.b = ((Value<<6)&0xC0)+((Value<<4)&0x30)+((Value<<2)&0x0C)+((Value)&0x03); + + if (ordenador.bw!=0) { + int final; + final=(((int)color.r)*3+((int)color.g)*6+((int)color.b))/10; + color.r=color.g=color.b=(unsigned char)final; + } + // Color mode + + SDL_SetColors (ordenador.screen, &color, 32+entry, 1); // set 16 colors from the 16th + + if (ordenador.bpp!=1) { + colors[entry+16]=SDL_MapRGB(screen->format,color.r,color.g,color.b); + } +} + +void Z80free_Out (register word Port, register byte Value) { + + // Microdrive access + + register word maskport; + + if (((Port&0x0001)==0)||((Port>=0x4000)&&(Port<0x8000))) { + do_contention(); + } + + // ULAPlus + if (Port == 0xBF3B) { + ordenador.ulaplus_reg = Value; + return; + } + if (Port == 0xFF3B) { + if (ordenador.ulaplus_reg==0x40) { // mode + ordenador.ulaplus=Value&0x01; + return; + } + if (ordenador.ulaplus_reg<0x40) { // register set mode + ordenador.ulaplus_palete[ordenador.ulaplus_reg]=Value; + set_palete_entry(ordenador.ulaplus_reg,Value); + } + } + + if(((Port &0x0018)!=0x0018)&&(ordenador.mdr_active)) + microdrive_out(Port,Value); + + // ULA port (A0 low) + + if (!(Port & 0x0001)) { + ordenador.port254 = (unsigned char) Value; + ordenador.border = (((unsigned char) Value) & 0x07); + + if (ordenador.pause) { + if (Value & 0x10) + ordenador.sound_bit = 1; + else + ordenador.sound_bit = 0; // assign to SOUND_BIT the value + } + } + + // Memory page (7FFD & 1FFD) + + if (ordenador.mode128k==3) { + maskport=0x0FFD; + } else { + maskport=0x3FFD; + } + + if (((Port|maskport) == 0x7FFD) && (0 == (ordenador.mport1 & 0x20))) { + ordenador.mport1 = (unsigned char) Value; + set_memory_pointers (); // set the pointers + } + + if (((Port|maskport) == 0x1FFD) && (0 == (ordenador.mport1 & 0x20))) { + ordenador.mport2 = (unsigned char) Value; + set_memory_pointers (); // set the pointers + } + + // Sound chip (AY-3-8912) + + if (((Port|maskport) == 0xFFFD)&&(ordenador.ay_emul)) + ordenador.ay_latch = ((unsigned int) (Value & 0x0F)); + + if (((Port|maskport) == 0xBFFD)&&(ordenador.ay_emul)) { + ordenador.ay_registers[ordenador.ay_latch] = (unsigned char) Value; + if (ordenador.ay_latch == 13) + ordenador.ay_envel_way = 2; // start cycle + } +} + + +byte Z80free_In (register word Port) { + + static unsigned int temporal_io; + byte pines; + + if (((Port&0x0001)==0)||((Port>=0x4000)&&(Port<0x8000))) { + do_contention(); + } + + temporal_io = (unsigned int) Port; + + if (Port == 0xFF3B) { + if (ordenador.ulaplus_reg==0x40) { // mode + return(ordenador.ulaplus&0x01); + } + if (ordenador.ulaplus_reg<0x40) { // register set mode + return(ordenador.ulaplus_palete[ordenador.ulaplus_reg]); + } + } + + if (!(temporal_io & 0x0001)) { + pines = 0xBF; // by default, sound bit is 0 + if (!(temporal_io & 0x0100)) + pines &= ordenador.s8; + if (!(temporal_io & 0x0200)) + pines &= ordenador.s9; + if (!(temporal_io & 0x0400)) + pines &= ordenador.s10; + if (!(temporal_io & 0x0800)) + pines &= ordenador.s11; + if (!(temporal_io & 0x1000)) + pines &= ordenador.s12; + if (!(temporal_io & 0x2000)) + pines &= ordenador.s13; + if (!(temporal_io & 0x4000)) + pines &= ordenador.s14; + if (!(temporal_io & 0x8000)) + pines &= ordenador.s15; + + if (ordenador.pause) { + if (ordenador.issue == 2) { + if (ordenador.port254 & 0x18) + pines |= 0x40; + } else { + if (ordenador.port254 & 0x10) + pines |= 0x40; + } + } else { + if (ordenador.tape_readed) + pines |= 0x40; // sound input + else + pines &= 0xBF; // sound input + } + return (pines); + } + + // Joystick + if (!(temporal_io & 0x0020)) { + if (ordenador.joystick == 1) { + return (ordenador.js); + } else { + return 0; // if Kempston is not selected, emulate it, but always 0 + } + } + + if ((temporal_io == 0xFFFD)&&(ordenador.ay_emul)) + return (ordenador.ay_registers[ordenador.ay_latch]); + + // Microdrive access + + if(((Port &0x0018)!=0x0018)&&(ordenador.mdr_active)) + return(microdrive_in(Port)); + + pines=bus_empty(); + + return (pines); +} + +void set_volume (unsigned char volume) { + + unsigned char vol2; + int bucle; + + if (volume > 64) + vol2 = 64; + else + vol2 = volume; + + ordenador.volume = vol2; + + for (bucle = 0; bucle < 4; bucle++) { + ordenador.sample0[bucle] = 0; + ordenador.sample1[bucle] = 0; + ordenador.sample1b[bucle] = 0; + } + + switch (ordenador.format) { + case 0: // 8 bits/sample + ordenador.sample1[0] = 1 * vol2; + ordenador.sample1[1] = 1 * vol2; + ordenador.sample1b[0] = 1; + ordenador.sample1b[1] = 1; + break; + case 1: // 16 bits/sample, Little Endian + ordenador.sample1[0] = 1 * vol2; + ordenador.sample1[1] = 1 * vol2; + ordenador.sample1[2] = 1 * vol2; + ordenador.sample1[3] = 1 * vol2; + ordenador.sample1b[0] = 1; + ordenador.sample1b[1] = 1; + ordenador.sample1b[2] = 1; + ordenador.sample1b[3] = 1; + break; + case 2: // 16 bits/sample, Big Endian + ordenador.sample1[0] = 1 * vol2; + ordenador.sample1[1] = 1 * vol2; + ordenador.sample1[2] = 1 * vol2; + ordenador.sample1[3] = 1 * vol2; + ordenador.sample1b[0] = 1; + ordenador.sample1b[1] = 1; + ordenador.sample1b[2] = 1; + ordenador.sample1b[3] = 1; + break; + } +} diff --git a/src/computer.h b/src/computer.h index da75aa3..5bd2b8c 100644 --- a/src/computer.h +++ b/src/computer.h @@ -1,217 +1,220 @@ -/* - * Copyright 2003-2009 (C) Raster Software Vigo (Sergio Costas) - * This file is part of FBZX - * - * FBZX 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 3 of the License, or - * (at your option) any later version. - * - * FBZX 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, see . - * - */ - -#ifndef computer_h -#define computer_h - -#include -#include - -// #define MUT - -extern char salir; - -enum tapmodes {TAP_GUIDE, TAP_DATA, TAP_PAUSE, TAP_TRASH, TAP_STOP, TAP_PAUSE2, TZX_PURE_TONE, - TZX_SEQ_PULSES, TAP_FINAL_BIT, TAP_PAUSE3}; -enum taptypes {TAP_TAP, TAP_TZX}; - -struct computer { - - unsigned int temporal_io; - - // screen private global variables - SDL_Surface *screen; - unsigned char *screenbuffer; - unsigned int screen_width; - unsigned int translate[6144],translate2[6144]; - unsigned char zaurus_mini; - unsigned char text_mini; - unsigned char dblscan; - unsigned char bw; - - int contador_flash; - - unsigned int *p_translt,*p_translt2; - unsigned char *pixel; // current address - char border,flash; - int currline,currpix; - - int tstados_counter; // counts tstates leaved to the next call - int resx,resy,bpp; // screen resolutions - int init_line; // cuantity to add to the base address to start to paint - int next_line; // cuantity to add when we reach the end of line to go to next line - int next_scanline; // cuantity to add to pass to the next scanline - int first_line; // first line to start to paint - int last_line; // last line to paint - int first_pixel; // first pixel of a line to paint - int last_pixel; // last pixel of a line to paint - int next_pixel; // next pixel - int pixancho,pixalto; // maximum pixel value for width and height - int jump_pixel; - unsigned char screen_snow; // 0-> no emulate snow; 1-> emulate snow - unsigned char contended_zone; // 0-> no contention; 1-> contention possible - int cicles_counter; // counts how many pixel clock cicles passed since las interrupt - - char ulaplus; // 0 = inactive; 1 = active - unsigned char ulaplus_reg; // contains the last selected register in the ULAPlus - unsigned char ulaplus_palete[64]; // contains the current palete - - // keyboard private global variables - - unsigned char s8,s9,s10,s11,s12,s13,s14,s15; - unsigned char k8,k9,k10,k11,k12,k13,k14,k15; - unsigned char readed; - unsigned char tab_extended; - unsigned char esc_again; - - // kempston joystick private global variables - - unsigned char js,jk; - - // Linux joystick private global variables - - unsigned char use_js; - unsigned char updown,leftright; - - // sound global variables - - int tst_sample; // number of tstates per sample - int freq; // frequency for reproduction - int format; // 0: 8 bits, 1: 16 bits LSB, 2: 16 bits MSB - signed char sign; // 0: unsigned; 1: signed - int channels; // number of channels - int buffer_len; // sound buffer length (in samples) - int increment; // cuantity to add to jump to the next sample - unsigned char volume; // volume - unsigned char sample1[4]; // buffer with precalculated sample 1 (for buzzer) - unsigned char sample1b[4]; // buffer with prec. sample 1 (for AY-3-8912) - unsigned char sample0[4]; // buffer with precalculated sample 0 - unsigned char sound_bit; - unsigned int tstados_counter_sound; - unsigned char *current_buffer; - unsigned char num_buff; - unsigned int sound_cuantity; // counter for the buffer - unsigned char ay_registers[16]; // registers for the AY emulation - unsigned int aych_a,aych_b,aych_c,aych_n,aych_envel; // counters for AY emulation - unsigned char ayval_a,ayval_b,ayval_c,ayval_n; - unsigned char ay_emul; // 0: no AY emulation; 1: AY emulation - unsigned char vol_a,vol_b,vol_c; - unsigned int tst_ay; - unsigned int tst_ay2; - unsigned int ay_latch; - signed char ay_envel_value; - unsigned char ay_envel_way; - unsigned char sound_current_value; - - // bus global variables - - unsigned char bus_counter; - unsigned char bus_value; - unsigned char issue; // 2= 48K issue 2, 3= 48K issue 3 - unsigned char mode128k; // 0=48K, 1=128K, 2=+2, 3=+3 - unsigned char joystick; // 0=cursor, 1=kempston, 2=sinclair1, 3=sinclair2 - unsigned char port254; - - - // tape global variables - - enum tapmodes tape_current_mode; - unsigned char pause; // 1=tape stop - enum taptypes tape_file_type; - unsigned int tape_counter0; - unsigned int tape_counter1; - unsigned int tape_counter_rep; - unsigned char tape_byte; - unsigned char tape_bit; - unsigned char tape_readed; - unsigned int tape_byte_counter; - unsigned int tape_pause_at_end; - FILE *tap_file; - unsigned char tape_fast_load; // 0 normal load; 1 fast load - unsigned char current_tap[2049]; - - unsigned char tape_current_bit; - unsigned int tape_block_level; - unsigned int tape_sync_level0; - unsigned int tape_sync_level1; - unsigned int tape_bit0_level; - unsigned int tape_bit1_level; - unsigned char tape_bits_at_end; - unsigned int tape_loop_counter; - long tape_loop_pos; - - unsigned char tape_write; // 0 can't write; 1 can write - - // Microdrive global variables - FILE *mdr_file; // Current microdrive file - unsigned char mdr_current_mdr[2049]; // current path and name for microdrive file - unsigned char mdr_active; // 0: not installed; 1: installed - unsigned char mdr_paged; // 0: not pagined; 1: pagined - unsigned int mdr_tapehead; // current position in the tape - unsigned int mdr_bytes; // number of bytes read or written in this transfer - unsigned int mdr_maxbytes; // maximum number of bytes to read or write in this transfer - unsigned int mdr_gap; // TSTATEs remaining for GAP end - unsigned int mdr_nogap; // TSTATEs remaining for next GAP - unsigned char mdr_cartridge[137923]; // current cartridge - unsigned char mdr_drive; // current drive - byte mdr_old_STATUS; // to detect an edge in COM CLK - unsigned char mdr_modified; // if a sector is stored, this change to know that it must be stored in the file - - // OSD global variables - - unsigned char osd_text[200]; - unsigned int osd_time; - - // pagination global variables - - unsigned char mport1,mport2; // ports for memory management (128K and +3) - unsigned int video_offset; // 0 for page 5, and 32768 for page 7 - unsigned char *block0,*block1,*block2,*block3; // pointers for memory access (one for each 16K block). - - // public - - unsigned char memoria[196608]; // memory (12 pages of 16K each one). 4 for ROM, and 8 for RAM - unsigned char shadowrom[8192]; // space for Interface I's ROMs - unsigned char interr; - unsigned char mustlock; - unsigned char other_ret; // 0=no change; 1=memory returns RET (201) - - unsigned char turbo; - SDL_Event keyboard_buffer[10]; - unsigned int kbd_buffer_pointer; -}; - -void computer_init(); -void register_screen(SDL_Surface *); -inline void show_screen(int); -inline void paint_pixels(unsigned char, unsigned char, unsigned char); -inline void read_keyboard(); -void fill_audio(void *udata,Uint8 *,int); -void set_volume(unsigned char); -inline void play_sound(unsigned int); -inline void emulate(int); -void ResetComputer(); -inline byte bus_empty(); -void set_memory_pointers(); -inline void play_ay(); -inline void paint_one_pixel(unsigned char *colour,unsigned char *address); -void computer_set_palete(); -void set_palete_entry(unsigned char entry, byte Value); - -#endif +/* + * Copyright 2003-2009 (C) Raster Software Vigo (Sergio Costas) + * This file is part of FBZX + * + * FBZX 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 3 of the License, or + * (at your option) any later version. + * + * FBZX 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, see . + * + */ + +#ifndef computer_h +#define computer_h + +#include +#include + +// #define MUT + +extern char salir; + +enum tapmodes {TAP_GUIDE, TAP_DATA, TAP_PAUSE, TAP_TRASH, TAP_STOP, TAP_PAUSE2, TZX_PURE_TONE, + TZX_SEQ_PULSES, TAP_FINAL_BIT, TAP_PAUSE3}; +enum taptypes {TAP_TAP, TAP_TZX}; + +struct computer { + + unsigned int temporal_io; + + // screen private global variables + SDL_Surface *screen; + unsigned char *screenbuffer; + unsigned int screen_width; + unsigned int translate[6144],translate2[6144]; + unsigned char zaurus_mini; + unsigned char text_mini; + unsigned char dblscan; + unsigned char bw; + + int contador_flash; + + unsigned int *p_translt,*p_translt2; + unsigned char *pixel; // current address + char border,flash; + int currline,currpix; + + int tstados_counter; // counts tstates leaved to the next call + int resx,resy,bpp; // screen resolutions + int init_line; // cuantity to add to the base address to start to paint + int next_line; // cuantity to add when we reach the end of line to go to next line + int next_scanline; // cuantity to add to pass to the next scanline + int first_line; // first line to start to paint + int last_line; // last line to paint + int first_pixel; // first pixel of a line to paint + int last_pixel; // last pixel of a line to paint + int next_pixel; // next pixel + int pixancho,pixalto; // maximum pixel value for width and height + int jump_pixel; + unsigned char screen_snow; // 0-> no emulate snow; 1-> emulate snow + unsigned char contended_zone; // 0-> no contention; 1-> contention possible + int cicles_counter; // counts how many pixel clock cicles passed since las interrupt + + char ulaplus; // 0 = inactive; 1 = active + unsigned char ulaplus_reg; // contains the last selected register in the ULAPlus + unsigned char ulaplus_palete[64]; // contains the current palete + + // keyboard private global variables + + unsigned char s8,s9,s10,s11,s12,s13,s14,s15; + unsigned char k8,k9,k10,k11,k12,k13,k14,k15; + unsigned char readed; + unsigned char tab_extended; + unsigned char esc_again; + + // kempston joystick private global variables + + unsigned char js,jk; + + // Linux joystick private global variables + + unsigned char use_js; + unsigned char updown,leftright; + + // sound global variables + + int tst_sample; // number of tstates per sample + int freq; // frequency for reproduction + int format; // 0: 8 bits, 1: 16 bits LSB, 2: 16 bits MSB + signed char sign; // 0: unsigned; 1: signed + int channels; // number of channels + int buffer_len; // sound buffer length (in samples) + int increment; // cuantity to add to jump to the next sample + unsigned char volume; // volume + unsigned char sample1[4]; // buffer with precalculated sample 1 (for buzzer) + unsigned char sample1b[4]; // buffer with prec. sample 1 (for AY-3-8912) + unsigned char sample0[4]; // buffer with precalculated sample 0 + unsigned char sound_bit; + unsigned int tstados_counter_sound; + unsigned char *current_buffer; + unsigned char num_buff; + unsigned int sound_cuantity; // counter for the buffer + unsigned char ay_registers[16]; // registers for the AY emulation + unsigned int aych_a,aych_b,aych_c,aych_n,aych_envel; // counters for AY emulation + unsigned char ayval_a,ayval_b,ayval_c,ayval_n; + unsigned char ay_emul; // 0: no AY emulation; 1: AY emulation + unsigned char vol_a,vol_b,vol_c; + unsigned int tst_ay; + unsigned int tst_ay2; + unsigned int ay_latch; + signed char ay_envel_value; + unsigned char ay_envel_way; + unsigned char sound_current_value; + + // bus global variables + + unsigned char bus_counter; + unsigned char bus_value; + unsigned char issue; // 2= 48K issue 2, 3= 48K issue 3 + unsigned char mode128k; // 0=48K, 1=128K, 2=+2, 3=+3 + unsigned char joystick; // 0=cursor, 1=kempston, 2=sinclair1, 3=sinclair2 + unsigned char port254; + + + // tape global variables + + enum tapmodes tape_current_mode; + unsigned char pause; // 1=tape stop + enum taptypes tape_file_type; + unsigned int tape_counter0; + unsigned int tape_counter1; + unsigned int tape_counter_rep; + unsigned char tape_byte; + unsigned char tape_bit; + unsigned char tape_readed; + unsigned int tape_byte_counter; + unsigned int tape_pause_at_end; + FILE *tap_file; + unsigned char tape_fast_load; // 0 normal load; 1 fast load + unsigned char current_tap[2049]; + + unsigned char tape_current_bit; + unsigned int tape_block_level; + unsigned int tape_sync_level0; + unsigned int tape_sync_level1; + unsigned int tape_bit0_level; + unsigned int tape_bit1_level; + unsigned char tape_bits_at_end; + unsigned int tape_loop_counter; + long tape_loop_pos; + + unsigned char tape_write; // 0 can't write; 1 can write + + // Microdrive global variables + FILE *mdr_file; // Current microdrive file + unsigned char mdr_current_mdr[2049]; // current path and name for microdrive file + unsigned char mdr_active; // 0: not installed; 1: installed + unsigned char mdr_paged; // 0: not pagined; 1: pagined + unsigned int mdr_tapehead; // current position in the tape + unsigned int mdr_bytes; // number of bytes read or written in this transfer + unsigned int mdr_maxbytes; // maximum number of bytes to read or write in this transfer + unsigned int mdr_gap; // TSTATEs remaining for GAP end + unsigned int mdr_nogap; // TSTATEs remaining for next GAP + unsigned char mdr_cartridge[137923]; // current cartridge + unsigned char mdr_drive; // current drive + byte mdr_old_STATUS; // to detect an edge in COM CLK + unsigned char mdr_modified; // if a sector is stored, this change to know that it must be stored in the file + + // OSD global variables + + unsigned char osd_text[200]; + unsigned int osd_time; + + // pagination global variables + + unsigned char mport1,mport2; // ports for memory management (128K and +3) + unsigned int video_offset; // 0 for page 5, and 32768 for page 7 + unsigned char *block0,*block1,*block2,*block3; // pointers for memory access (one for each 16K block). + + // public + + unsigned char memoria[196608]; // memory (12 pages of 16K each one). 4 for ROM, and 8 for RAM + unsigned char shadowrom[8192]; // space for Interface I's ROMs + unsigned char interr; + unsigned char mustlock; + unsigned char other_ret; // 0=no change; 1=memory returns RET (201) + + unsigned char turbo; + unsigned int kbd_buffer_pointer; + unsigned char *key; + SDL_Joystick *joystick_sdl[2]; + int joy_axis_x_state[2]; + int joy_axis_y_state[2]; +}; + +void computer_init(); +void register_screen(SDL_Surface *); +inline void show_screen(int); +inline void paint_pixels(unsigned char, unsigned char, unsigned char); +inline void read_keyboard(); +void fill_audio(void *udata,Uint8 *,int); +void set_volume(unsigned char); +inline void play_sound(unsigned int); +inline void emulate(int); +void ResetComputer(); +inline byte bus_empty(); +void set_memory_pointers(); +inline void play_ay(); +inline void paint_one_pixel(unsigned char *colour,unsigned char *address); +void computer_set_palete(); +void set_palete_entry(unsigned char entry, byte Value); + +#endif diff --git a/src/emulator.c b/src/emulator.c index 9fa4465..15ed50b 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -219,7 +219,7 @@ void load_rom(char type) { void init_screen(int resx,int resy,int depth,int fullscreen,int dblbuffer,int hwsurface) { - int retorno,bucle,bucle2,valores,ret2; + int retorno,bucle,bucle2,valores,ret2,joystick_number; unsigned char value; //if (sound_type!=3) @@ -239,8 +239,11 @@ void init_screen(int resx,int resy,int depth,int fullscreen,int dblbuffer,int hw ordenador.use_js=1; if(SDL_NumJoysticks()>0){ // Open joystick - for (bucle=0;bucle2) joystick_number = 2; //Open max 2 joysticks + for (bucle=0;buclepixels; ancho=screen->w; @@ -996,7 +997,15 @@ void create_scrfile() { print_string(videomem,"SCR file will be saved in:",-1,132,12,0,ancho); print_string(videomem,path_snaps,0,152,12,0,ancho); - retorno=ask_filename(nombre2,84,"scr",path_snaps); + if (strlen(ordenador.current_tap)) + { + name=strrchr(ordenador.current_tap,'/'); + if (name) name++; else name = ordenador.current_tap; + } + else + name=NULL; + + retorno=ask_filename(nombre2,84,"scr",path_snaps, name); clean_screen(); @@ -1041,10 +1050,11 @@ void create_scrfile() { } -int ask_filename(char *nombre_final,int y_coord,char *extension, char *path) { +int ask_filename(char *nombre_final,int y_coord,char *extension, char *path, char *name) { int longitud,retorno; unsigned char nombre[37],nombre2[38]; + char *ptr; unsigned char *videomem; int ancho; @@ -1052,10 +1062,29 @@ int ask_filename(char *nombre_final,int y_coord,char *extension, char *path) { videomem=screen->pixels; ancho=screen->w; - nombre[0]=127; - nombre[1]=0; - longitud=0; retorno=0; + + if (!name||(strlen(name)>36)) + { + nombre[0]=127; + nombre[1]=0; + } + else + { + strcpy(nombre,name); + ptr = strrchr (nombre, '.'); + if (ptr) //remove the extension + { + *ptr = 127; + *(ptr+1) = 0; + } + else + nombre[strlen(nombre)-1]=127; + nombre[strlen(nombre)]=0; + } + + longitud=strlen(nombre)-1; + do { sprintf (nombre2, " %s.%s ", nombre,extension); @@ -1452,6 +1481,7 @@ void save_z80file() { unsigned char *videomem; int ancho,retorno; unsigned char nombre2[1024]; + char *name; videomem=screen->pixels; ancho=screen->w; @@ -1464,8 +1494,15 @@ void save_z80file() { print_string(videomem,"Snapshot will be saved in:",-1,132,12,0,ancho); print_string(videomem,path_snaps,0,152,12,0,ancho); - - retorno=ask_filename(nombre2,84,"z80", path_snaps); + if (strlen(ordenador.current_tap)) + { + name=strrchr(ordenador.current_tap,'/'); + if (name) name++; else name = ordenador.current_tap; + } + else + name=NULL; + + retorno=ask_filename(nombre2,84,"z80", path_snaps, name); clean_screen(); @@ -1845,7 +1882,7 @@ void keyboard_menu() { buffer=buffer2-ordenador.bpp; } } - print_copy(screen->pixels,screen->w); + //print_copy(screen->pixels,screen->w); wait_key(); clean_screen(); } diff --git a/src/menus.h b/src/menus.h index 9fd52f4..eefcc59 100644 --- a/src/menus.h +++ b/src/menus.h @@ -45,7 +45,7 @@ void create_mdrfile(); void microdrive_menu(); void keyboard_menu(); void load_scrfile(); -int ask_filename(char *nombre,int y_coord,char *extension, char *path); +int ask_filename(char *nombre,int y_coord,char *extension, char *path, char *name); void create_scrfile(); void do_poke(); int ask_value(int *final_value,int y_coord,int max_value);