#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sprinter.h>
#include <sprinter_mem.h>

/*
 * Exercises the ESTEX EMM page allocator + bank_read/bank_write helpers.
 *
 * Plan:
 *  1. Show free-page count via mem_info.
 *  2. Allocate 3 pages → block id.
 *  3. For each page in the block, write a recognizable pattern via
 *     bank_write, then read it back via bank_read into a near buffer.
 *  4. Cross-check the readback to prove pages are independent.
 *  5. Free the block, show the free-page count again.
 */

uint32_t buff[256];

static void show_mem(const char *label)
{
    uint16_t total, free_pages;
    mem_info(&total, &free_pages);
    printf("  %s total=%u free=%u (each page = 16 KB)\n",
           label, total, free_pages);
}

int main(void)
{
    puts("Sprinter page allocator demo");
    puts("");
    
    memset(buff, 0, sizeof(buff));
    // printf("mem_io_ports_test() = 0x%02X\n", mem_io_ports_test());
    printf("buff size (sizeof) = %u\n", sizeof(buff));
    printf("buff size one element (sizeof) = %u\n", sizeof(buff[0]));
    printf("buff first element = %u\n", buff[0]);
    printf("buff last element = %u\n", buff[(sizeof(buff) / sizeof(buff[0])) - 1]);

    show_mem("before:");

    uint8_t blk = mem_alloc_pages(3);
    if (blk == 0) {
        puts("  mem_alloc_pages(3) failed");
        (void)getchar();
        return 1;
    }
    printf("  allocated block id = %u (3 pages)\n", blk);
    show_mem("after alloc:");

    /* Show the physical page numbers we got. */
    for (uint8_t i = 0; i < 3; i++) {
        uint8_t phys = mem_get_page(blk, i);
        printf("  page %u of block = phys 0x%02X\n", i, phys);
    }

    /* Write a 32-byte pattern at offset 0 of each page; pattern depends
     * on page index so we can distinguish them. */
    char buf[33];
    for (uint8_t i = 0; i < 3; i++) {
        uint8_t phys = mem_get_page(blk, i);
        for (int j = 0; j < 32; j++) {
            buf[j] = 'A' + (char)i;     /* page 0 -> 'A', page 1 -> 'B', page 2 -> 'C' */
        }
        buf[32] = 0;
        bank_write(phys, 0, buf, 32);
        printf("  wrote 32 x '%c' to page %u (phys 0x%02X)\n",
               'A' + i, i, phys);
    }

    /* Read back and verify each page has its own pattern. */
    puts("");
    puts("readback:");
    for (uint8_t i = 0; i < 3; i++) {
        uint8_t phys = mem_get_page(blk, i);
        memset(buf, 0, sizeof(buf));
        bank_read(phys, 0, buf, 32);
        buf[32] = 0;
        printf("  page %u (phys 0x%02X) first 32 bytes: \"%s\"\n",
               i, phys, buf);
    }

    /* Single-byte API spot check. */
    bank_store_byte(mem_get_page(blk, 1), 100, 0x42);
    uint8_t got = bank_load_byte(mem_get_page(blk, 1), 100);
    printf("\n  store/load single byte at page1[100]: 0x%02X (expect 0x42)\n", got);

    mem_free_block(blk);
    show_mem("after free:");

    puts("");
    puts("Press any key to exit.");
    (void)getchar();
    return 0;
}
