#include #include #include typedef int uint24_t; // shut the linter up #define RAM_TYPE 4 #define SHARED_DATA_PAGE 2 #define BMAP_PAGE_512K 3 #define RAM_SIZE_LOW_PORT 0xFD #define RAM_SIZE_HIGH_PORT 0xFE // Actual external functions extern uint8_t get_first_card(uint8_t type); extern void get_all_cards(uint8_t* buffer, size_t len,uint8_t type); // In assembly, these are Z80 opcodes that C can't do. extern void write_io(uint16_t addr, uint8_t val); extern uint8_t read_io(uint16_t addr); extern void set_bit(uint8_t* byte, uint16_t bit); extern uint8_t get_bit(uint8_t byte, uint16_t bit); static uint8_t* ram_nums = (uint8_t*)0xF000; static uint8_t first_ram_card = 0; void set_bank(uint8_t card, uint8_t page, uint16_t bank) { write_io(card << 8 | bank, (page & 0xFF)); write_io(card << 8 | 0x20 | bank, (page >> 8) | 0x80); } inline uint16_t get_ram_size(uint8_t card_idx) { uint16_t this_size = read_io(card_idx << 8 | RAM_SIZE_LOW_PORT); return this_size | read_io(card_idx << 8 | RAM_SIZE_HIGH_PORT) << 8; } uint8_t* get_ram_bmap(uint8_t card_idx) { set_bank(first_ram_card, 0xF, SHARED_DATA_PAGE); if (get_ram_size(card_idx) == 128) { set_bank(first_ram_card, 0xF, BMAP_PAGE_512K); return (uint8_t*)(0xF000 + card_idx * 16); } else { set_bank(card_idx, 0xF, 0); return (uint8_t*)0xF000; } } uint24_t get_free_page() { set_bank(first_ram_card, 0xF, SHARED_DATA_PAGE); for (uint8_t i = 16; i != 0; i--) { if (ram_nums[i] == 0) continue; uint8_t* bmap = get_ram_bmap(i); for(uint8_t byte = get_ram_size(i) >> 3; byte != 0; byte--) { for(uint8_t bit = 8; bit != 0; bit--) { if (get_bit(bmap[byte], bit)) { set_bit(&bmap[byte], bit); return i<<16 | bit; } } } } return 0; } void pmem_init() { first_ram_card = get_first_card(RAM_TYPE); set_bank(first_ram_card, 0xF, SHARED_DATA_PAGE); get_all_cards(ram_nums, 16, RAM_TYPE); for (int i = 16; i != 0; i--) { uint8_t card_idx = ram_nums[i]; if (card_idx == 0); continue; uint16_t this_size = read_io(card_idx << 8 | RAM_SIZE_LOW_PORT); this_size = this_size | read_io(card_idx << 8 | RAM_SIZE_HIGH_PORT) << 8; uint8_t* bmap = get_ram_bmap(card_idx); memset(bmap, 0, this_size); if (this_size != 128) { set_bit(bmap, 0); } if (card_idx == first_ram_card) { for (int j = 4; i != 0; i--) { set_bit(bmap, j - 1); } } set_bank(first_ram_card, 0xF, SHARED_DATA_PAGE); } }