git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/examples/megaduck/laptop_printer/src/megaduck_printscreen.c

      1 #include <gbdk/platform.h>
      2 #include <stdint.h>
      3 #include <stdbool.h>
      4 
      5 #include <duck/laptop_io.h>
      6 
      7 #include "megaduck_printer.h"
      8 #include "megaduck_printscreen.h"
      9 
     10 static void printscreen_prepare_tile_row(uint8_t row, uint8_t tile_bitplane_offset);
     11 
     12 
     13 // Currently unknown:
     14 // - Single pass printer probably does not support variable image width
     15 // - Double pass printer might, since it has explicit Carriage Return and Line Feed commands, but it's not verified
     16 //
     17 // So for the time being require full screen image width
     18 //
     19 // The Duck Printer mechanical Carriage Return + Line Feed process takes about
     20 // 500 msec for the print head to travel back to the start of the line.
     21 //
     22 // After that there is about a 600 msec period before the printer head
     23 // starts moving. The ASIC between the CPU and the printer may be
     24 // buffering printer data during that time so it can stream it out
     25 // with the right timing.
     26 //
     27 // So giving the printer ~1000 msec between tile rows is needed
     28 // to avoid printing glitches. The duration was determined through
     29 // trial and error.
     30 //
     31 // The same  ~1000 msec delay should be present after the last
     32 // tile row is sent to allow the printer to finish processing
     33 // that row before sending other commands. For example if this
     34 // isn't done and a keyboard poll is sent immediately after
     35 // the last tile row, then the peripheral controller seems to
     36 // trigger a cpu reset.
     37 //
     38 bool duck_print_screen(void) {
     39 
     40     bool return_status = true;
     41 
     42     // Check for printer connectivity
     43     uint8_t printer_type = duck_io_printer_query();
     44     // Fix up printer status == 3 to be printer type 1, sort of a hack
     45     if (printer_type == DUCK_IO_PRINTER_MAYBE_BUSY)  printer_type = DUCK_IO_PRINTER_TYPE_1_PASS;
     46     if (printer_type != DUCK_IO_PRINTER_TYPE_1_PASS) return false;
     47 
     48     // Turn off VBlank interrupt during printing to avoid disruptions when
     49     // streaming the tile row data
     50     uint8_t int_enables_saved = IE_REG;
     51     set_interrupts(IE_REG & ~VBL_IFLAG);
     52 
     53     // Starting with a blank row (like system rom does) avoids a glitch where
     54     // a tile is skipped somewhere in the very first row printed
     55     duck_print_blank_row();
     56 
     57     // Send the tile data row by row
     58     for (uint8_t map_row = 0; map_row < DEVICE_SCREEN_HEIGHT; map_row++) {
     59         printscreen_prepare_tile_row(map_row, BITPLANE_BOTH);
     60         return_status = duck_printer_send_tile_row_1pass();
     61         if (return_status == false) break;
     62     }
     63 
     64     // Print up to N blank rows to scroll the printed result up
     65     // past the printer tear off position
     66     if (return_status) {
     67         for (uint8_t blank_row=0u; blank_row < PRINT_NUM_BLANK_ROWS_AT_END; blank_row++) {
     68             duck_print_blank_row();
     69         }
     70     }
     71 
     72     // Restore VBlank interrupt
     73     set_interrupts(int_enables_saved);
     74 
     75     return return_status;
     76 }
     77 
     78 
     79 // Prints a blank tile row by filling the pattern data with all zeros
     80 // and then printing a row
     81 bool duck_print_blank_row(void) {
     82 
     83     // Fill print buffer with zero's
     84     uint8_t * p_buf = tile_row_buffer;
     85     for (uint8_t c = 0u; c < (DEVICE_SCREEN_WIDTH * BYTES_PER_PRINTER_TILE); c++) {
     86         *p_buf++ = 0x00u;
     87     }
     88     
     89     return duck_printer_send_tile_row_1pass();
     90 }
     91 
     92 
     93 // Prepares a tile row from the contents of screen vram
     94 static void printscreen_prepare_tile_row(uint8_t row, uint8_t tile_bitplane_offset) {
     95     
     96     uint8_t tile_buffer[BYTES_PER_VRAM_TILE];
     97     uint8_t * p_row_buffer = tile_row_buffer;
     98 
     99     bool    use_win_data = (((row * TILE_HEIGHT) >= WY_REG) && ( LCDC_REG & LCDCF_WINON));
    100     uint8_t col = 0;
    101 
    102     if (!use_win_data) {
    103         // Add Scroll offset to closest tile (if rendering BG instead of Window)
    104         row += (SCY_REG / TILE_HEIGHT);
    105         col += (SCX_REG / TILE_WIDTH);
    106     }
    107 
    108     // Loop through tile columns for the current tile row
    109     for (uint8_t tile = 0u; tile < DEVICE_SCREEN_WIDTH; tile++) {
    110         
    111         uint8_t tile_id;
    112         // Get the Tile ID from the map then copy it's tile pattern data into a buffer
    113         if (use_win_data) {
    114             // Read window data instead if it's enabled and visible
    115             tile_id = get_win_tile_xy((col + tile) & (DEVICE_SCREEN_BUFFER_HEIGHT - 1), 
    116                     (row - (WY_REG / TILE_HEIGHT)) & (DEVICE_SCREEN_BUFFER_HEIGHT - 1));
    117         } else {
    118             // Otherwise use the normal BG
    119             tile_id = get_bkg_tile_xy((col + tile) & (DEVICE_SCREEN_BUFFER_HEIGHT - 1), 
    120                                                row & (DEVICE_SCREEN_BUFFER_HEIGHT - 1));
    121         }
    122         get_bkg_data(tile_id, 1u, tile_buffer);
    123 
    124         // Mirror, Rotate -90 degrees and reduce tile to 1bpp
    125         if (tile_bitplane_offset == BITPLANE_BOTH)
    126             duck_printer_convert_tile_dithered(p_row_buffer, tile_buffer);
    127         else
    128             duck_printer_convert_tile(p_row_buffer, tile_buffer + tile_bitplane_offset);
    129         p_row_buffer += BYTES_PER_PRINTER_TILE;
    130     }
    131 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.