Thu, 11 Apr 2013 09:37:11 +0100
Check return value of fread()
philpem@18 | 1 | #define _STATE_C |
philpem@18 | 2 | #include <stddef.h> |
philpem@18 | 3 | #include <malloc.h> |
philpem@18 | 4 | #include <stdio.h> |
philpem@52 | 5 | #include "wd279x.h" |
philpem@112 | 6 | #include "wd2010.h" |
philpem@80 | 7 | #include "keyboard.h" |
philpem@18 | 8 | #include "state.h" |
philpem@18 | 9 | |
philpem@62 | 10 | int state_init(size_t base_ram_size, size_t exp_ram_size) |
philpem@18 | 11 | { |
philpem@18 | 12 | // Free RAM if it's allocated |
philpem@60 | 13 | if (state.base_ram != NULL) |
philpem@60 | 14 | free(state.base_ram); |
philpem@62 | 15 | if (state.exp_ram != NULL) |
philpem@62 | 16 | free(state.exp_ram); |
philpem@18 | 17 | |
philpem@18 | 18 | // Initialise hardware registers |
philpem@18 | 19 | state.romlmap = false; |
philpem@75 | 20 | state.idmarw = state.dmaen = state.dmaenb = false; |
philpem@75 | 21 | state.dma_count = state.dma_address = 0; |
philpem@75 | 22 | state.pie = 0; |
philpem@101 | 23 | state.ee = 0; |
philpem@75 | 24 | state.leds = 0; |
philpem@75 | 25 | state.genstat = 0; // FIXME: check this |
philpem@75 | 26 | state.bsr0 = state.bsr1 = 0; // FIXME: check this |
philpem@97 | 27 | state.timer_enabled = state.timer_asserted = false; |
philpem@62 | 28 | // Allocate Base RAM, making sure the user has specified a valid RAM amount first |
philpem@62 | 29 | // Basically: 512KiB minimum, 2MiB maximum, in increments of 512KiB. |
philpem@62 | 30 | if ((base_ram_size < 512*1024) || (base_ram_size > 2048*1024) || ((base_ram_size % (512*1024)) != 0)) |
philpem@18 | 31 | return -1; |
philpem@62 | 32 | state.base_ram = malloc(base_ram_size); |
philpem@60 | 33 | if (state.base_ram == NULL) |
philpem@18 | 34 | return -2; |
philpem@62 | 35 | state.base_ram_size = base_ram_size; |
philpem@62 | 36 | |
philpem@62 | 37 | // Now allocate expansion RAM |
philpem@62 | 38 | // The difference here is that we can have zero bytes of Expansion RAM; we're not limited to having a minimum of 512KiB. |
philpem@62 | 39 | if ((exp_ram_size > 2048*1024) || ((exp_ram_size % (512*1024)) != 0)) |
philpem@62 | 40 | return -1; |
philpem@62 | 41 | state.exp_ram = malloc(exp_ram_size); |
philpem@62 | 42 | if (state.exp_ram == NULL) |
philpem@62 | 43 | return -2; |
philpem@62 | 44 | state.exp_ram_size = exp_ram_size; |
philpem@18 | 45 | |
philpem@18 | 46 | // Load ROMs |
philpem@18 | 47 | FILE *r14c, *r15c; |
philpem@18 | 48 | r14c = fopen("roms/14c.bin", "rb"); |
philpem@55 | 49 | if (r14c == NULL) { |
philpem@55 | 50 | fprintf(stderr, "[state] Error loading roms/14c.bin.\n"); |
philpem@55 | 51 | return -3; |
philpem@55 | 52 | } |
philpem@18 | 53 | r15c = fopen("roms/15c.bin", "rb"); |
philpem@55 | 54 | if (r15c == NULL) { |
philpem@55 | 55 | fprintf(stderr, "[state] Error loading roms/15c.bin.\n"); |
philpem@55 | 56 | return -3; |
philpem@55 | 57 | } |
philpem@18 | 58 | |
philpem@18 | 59 | // get ROM file size |
philpem@18 | 60 | fseek(r14c, 0, SEEK_END); |
philpem@18 | 61 | size_t romlen = ftell(r14c); |
philpem@18 | 62 | fseek(r14c, 0, SEEK_SET); |
philpem@18 | 63 | fseek(r15c, 0, SEEK_END); |
philpem@18 | 64 | size_t romlen2 = ftell(r15c); |
philpem@18 | 65 | fseek(r15c, 0, SEEK_SET); |
philpem@55 | 66 | if (romlen2 != romlen) { |
philpem@55 | 67 | fprintf(stderr, "[state] ROMs are not the same size!\n"); |
philpem@55 | 68 | return -3; |
philpem@55 | 69 | } |
philpem@55 | 70 | if ((romlen + romlen2) > ROM_SIZE) { |
philpem@55 | 71 | fprintf(stderr, "[state] ROM files are too large!\n"); |
philpem@55 | 72 | return -3; |
philpem@55 | 73 | } |
philpem@18 | 74 | |
philpem@18 | 75 | // sanity checks completed; load the ROMs! |
philpem@18 | 76 | uint8_t *romdat1, *romdat2; |
philpem@18 | 77 | romdat1 = malloc(romlen); |
philpem@18 | 78 | romdat2 = malloc(romlen2); |
philpem@138 | 79 | if (fread(romdat1, 1, romlen, r15c) != romlen) { |
philpem@138 | 80 | fprintf(stderr, "[state] Error reading ROM 15C.\n"); |
philpem@138 | 81 | return -3; |
philpem@138 | 82 | } |
philpem@138 | 83 | if (fread(romdat2, 1, romlen2, r14c) != romlen) { |
philpem@138 | 84 | fprintf(stderr, "[state] Error reading ROM 14C.\n"); |
philpem@138 | 85 | return -3; |
philpem@138 | 86 | } |
philpem@18 | 87 | |
philpem@18 | 88 | // convert the ROM data |
philpem@18 | 89 | for (size_t i=0; i<(romlen + romlen2); i+=2) { |
philpem@18 | 90 | state.rom[i+0] = romdat1[i/2]; |
philpem@18 | 91 | state.rom[i+1] = romdat2[i/2]; |
philpem@18 | 92 | } |
philpem@18 | 93 | |
philpem@18 | 94 | // TODO: if ROM buffer not filled, repeat the ROM data we read until it is (wraparound emulation) |
philpem@18 | 95 | |
philpem@18 | 96 | // free the data arrays and close the files |
philpem@18 | 97 | free(romdat1); |
philpem@18 | 98 | free(romdat2); |
philpem@18 | 99 | fclose(r14c); |
philpem@18 | 100 | fclose(r15c); |
philpem@18 | 101 | |
philpem@52 | 102 | // Initialise the disc controller |
philpem@52 | 103 | wd2797_init(&state.fdc_ctx); |
philpem@80 | 104 | // Initialise the keyboard controller |
philpem@80 | 105 | keyboard_init(&state.kbd); |
philpem@52 | 106 | |
philpem@18 | 107 | return 0; |
philpem@18 | 108 | } |
philpem@18 | 109 | |
philpem@18 | 110 | void state_done() |
philpem@18 | 111 | { |
philpem@60 | 112 | if (state.base_ram != NULL) { |
philpem@60 | 113 | free(state.base_ram); |
philpem@60 | 114 | state.base_ram = NULL; |
philpem@18 | 115 | } |
philpem@62 | 116 | |
philpem@62 | 117 | if (state.exp_ram != NULL) { |
philpem@62 | 118 | free(state.exp_ram); |
philpem@62 | 119 | state.exp_ram = NULL; |
philpem@62 | 120 | } |
philpem@62 | 121 | |
philpem@52 | 122 | // Deinitialise the disc controller |
philpem@52 | 123 | wd2797_done(&state.fdc_ctx); |
philpem@112 | 124 | wd2010_done(&state.hdc_ctx); |
philpem@18 | 125 | } |
philpem@18 | 126 | |
philpem@18 | 127 |