#include "zx_screen.h" #include "z80.h" #include "zx_ula.h" #include #include "zx_tape.h" namespace zxscreen { uint32_t palette[16] = { 0x000000, 0x000080, 0x800000, 0x800080, 0x008000, 0x008080, 0x808000, 0x808080, 0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF }; SDL_Window *win = nullptr; SDL_Renderer *ren = nullptr; SDL_Texture *tex = nullptr; uint32_t time=0; uint32_t t_screen = 0; uint8_t t_flash = 0; bool flash = false; int pixels_draw = 0; uint16_t pixel_addr[69888]; uint16_t color_addr[69888]; uint8_t zx_pixels[352*296]; uint8_t *ptr_pixel = zx_pixels; void create_tables() { uint32_t count = 0; uint16_t *ptr_pixel = pixel_addr; uint16_t *ptr_color = color_addr; // vsync for (int i=0; i<224*16;++i) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; } // Upper border for (int i=0; i<48;++i) { // hsync for (int j=0;j<48;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; } //border for (int j=0;j<176;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; } } // scanlines for (uint8_t y=0; y<192; ++y) { // hsync for (int j=0;j<48;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; } // Left border for (int j=0;j<24;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; } // Actual screen for (uint8_t x=0;x<32;++x) { uint16_t color = 0x5800 + x + (y>>3)*32; uint16_t address = 0x4000 | (x&0x1f) | ((y&0x7)<<8) | ((y&0x38)<<2) | ((y&0xc0)<<5); for (int i=7;i>0;i-=2) { *(ptr_pixel++) = (address & 0x1FFF) | (i << 13); *(ptr_color++) = color; count+=2; } } // Right border for (int j=0;j<24;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; } } // Lower border for (int i=0; i<56;++i) { // hsync for (int j=0;j<48;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; } //border for (int j=0;j<176;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; } } printf("COUNT: %i\n", count); } void show() { if (win) return; win = SDL_CreateWindow("ZX Spectrum Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 352, 296, SDL_WINDOW_SHOWN); ren = SDL_CreateRenderer(win, -1, 0); tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 352, 296); create_tables(); redraw(); } void refresh(const uint8_t dt) { const uint8_t* memory = z80::getMem(); const uint8_t border_color = zx_ula::get_border_color(); for (int i=0;i>3)&0x7; if ((color&0x80) && flash) { c1=c2; c2=color&0x7; } if ((color&0x40)) { c1 |= 0x8; c2 |= 0x8; } uint16_t address = (0x4000) | (pixel_addr[t_screen]&0x1FFF); uint8_t mask = 1 << (pixel_addr[t_screen]>>13); uint8_t block = memory[address]; *(ptr_pixel++)=(block&mask) ? c1 : c2; mask>>=1; *(ptr_pixel++)=(block&mask) ? c1 : c2; } pixels_draw+=2; } t_screen++; /*if (pixels_draw>352*296) { printf("PIXELS OVERFLOW: %i\n", pixels_draw); }*/ if (t_screen>=69888) { //printf("PIXELS DRAWN: %i\n", pixels_draw); pixels_draw=0; t_flash++; if (t_flash==16) { t_flash=0; flash = !flash; } t_screen=0; ptr_pixel = zx_pixels; redraw(); //while (SDL_GetTicks()-time < 20) {} //time = SDL_GetTicks(); z80::interrupt(); } } } void redraw() { if (zx_tape::berserk()) return; Uint32* pixels; int pitch; SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch); for (int i=0; i<352*296;++i) *(pixels++) = palette[zx_pixels[i]]; SDL_UnlockTexture(tex); SDL_RenderCopy(ren, tex, NULL, NULL); SDL_RenderPresent(ren); } }