diff --git a/source/emu.c b/source/emu.c index 5ad75b2..7335075 100644 --- a/source/emu.c +++ b/source/emu.c @@ -46,22 +46,23 @@ void emu_init () // Set some sane defaults emu_vsync = 1; + emu_hires = 2; // Setup the video hardware video_init(); #if 1 crc = 0xffff; // Load the appropriate bios - if (load_bin("BASIC.ROM", 0xD000, 0x3000, &crc)) { - valid_crc = valid_rom_crc(crc); - iprintf("BIOS CRC16 %04x (%s)\n", crc, (valid_crc) ? "Valid" : "Invalid"); - // Refuse to load a wrong bios - if (!valid_crc) - while (1); - } else { - iprintf("No BASIC.ROM found. Halting."); + if (load_bin("BASIC.ROM", 0xD000, 0x3000, &crc) < 0) { + print_msg("No BASIC.ROM found. Halting."); while (1); } + + valid_crc = valid_rom_crc(crc); + iprintf("BIOS CRC16 %04x (%s)\n", crc, (valid_crc) ? "Valid" : "Invalid"); + // Refuse to load the incorrect bios + if (!valid_crc) + while (1); // Load the disk rom in place load_buf(disk_rom, 0xc600, 0x100); @@ -76,8 +77,6 @@ void emu_init () } #endif - basename = NULL; - // Used by the fps counter frames_done = 0; vblanks = 0; @@ -100,8 +99,11 @@ void emu_run () update_input(); frames_done++; - if (keysDown()&KEY_START) + if (keysDown()&KEY_START) { + irqDisable(IRQ_VBLANK); pause_menu(); + irqEnable(IRQ_VBLANK); + } sound_play(); diff --git a/source/emu.h b/source/emu.h index bada6e5..0c2d461 100644 --- a/source/emu.h +++ b/source/emu.h @@ -8,15 +8,16 @@ #include "mem.h" #include "state.h" -#define INPUT_JSTK 0 -#define INPUT_KBD 1 +#define INPUT_JOYSTICK 0 +#define INPUT_KEYBOARD 1 int emu_vsync; int emu_input; int emu_screen; int emu_scale; +int emu_hires; -static char *basename = NULL; +char *basename; void emu_init (); void emu_run (); diff --git a/source/input.c b/source/input.c index 000ac27..a113691 100644 --- a/source/input.c +++ b/source/input.c @@ -25,13 +25,13 @@ void update_input () keys = keysDown() | keysHeld(); // Send keyboard scancodes when a key is pressed - if (emu_input == INPUT_KBD && (keys&0xfff)) { + if (emu_input == INPUT_KEYBOARD && (keys&0xfff)) { int bit_set = __builtin_ffs(keys); if (bit_set) keybd_latch = 0x80 ^ key_map[bit_set-1]; } - if (emu_input == INPUT_JSTK) { + if (emu_input == INPUT_JOYSTICK) { jstk_btn[0] = (keys&KEY_X) ? 0x80 : 0x00; jstk_btn[1] = (keys&KEY_Y) ? 0x80 : 0x00; jstk_btn[2] = (keys&KEY_B) ? 0x80 : 0x00; diff --git a/source/main.c b/source/main.c index a393900..9d0c8a0 100644 --- a/source/main.c +++ b/source/main.c @@ -42,7 +42,7 @@ int main(int argc, char **argv) /*load_disk("Round About (1983)(Datamost).dsk");*/ /*load_disk("Bug Attack (1981)(Cavalier Computer).dsk");*/ // Scroller - load_disk("TetrisII.DSK"); + /*load_disk("TetrisII.DSK");*/ // Mixed mode /*load_disk("tetris48k.nib");*/ // Lowres @@ -53,7 +53,11 @@ int main(int argc, char **argv) // SP Crash /*load_disk("Apple II Business Graphics 1.0 (1981).nib");*/ } else { - load_disk(argv[1]); + if (!load_disk(argv[1])) { + print_msg("Cannot open the selected rom!"); + exit(0); + } + basename = argv[1]; } emu_run(); diff --git a/source/menu.c b/source/menu.c index bdfd603..2531f4c 100644 --- a/source/menu.c +++ b/source/menu.c @@ -7,6 +7,7 @@ typedef struct entry_t { const int opts_no; const char *opts[10]; int *opt_ptr; + int confirm; int (*cb)(int); } entry_t; @@ -51,27 +52,27 @@ static int opt_exit (const int sel) static int opt_hires (const int sel) { video_set_hires(sel); + return 1; } -static int sel_slot_l = 0, sel_slot_s = 0, sel_hires = 0; +static int sel_slot_l = 0, sel_slot_s = 0; const static struct page_t paused_pg = { "Paused", 8, (const entry_t []){ - { "Vsync", 2, { "No", "Yes" }, &emu_vsync, opt_vsync }, - { "Scale", 2, { "No", "Yes" }, &emu_scale, opt_scale }, - { "Screen", 2, { "Top", "Bottom" }, &emu_screen, opt_screen }, - { "Hires mode", 2, { "B/W", "Color" }, &sel_hires, opt_hires }, - { "Map keys to", 2, { "joystick", "keyboard" }, &emu_input, opt_input }, - { "Save state", 9, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, &sel_slot_s, state_save }, - { "Load state", 9, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, &sel_slot_l, state_load }, - { "Exit", 0, { }, NULL, opt_exit }, + { "Vsync", 2, { "No", "Yes" }, &emu_vsync, 0, opt_vsync }, + { "Scale", 2, { "No", "Yes" }, &emu_scale, 0, opt_scale }, + { "Screen", 2, { "Top", "Bottom" }, &emu_screen, 0, opt_screen }, + { "Hires mode", 3, { "B/W", "Old", "Color" }, &emu_hires, 0, opt_hires }, + { "Map keys to", 2, { "joystick", "keyboard" }, &emu_input, 0, opt_input }, + { "Save state", 9, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, &sel_slot_s, 1, state_save }, + { "Load state", 9, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, &sel_slot_l, 1, state_load }, + { "Exit", 0, { }, NULL, 1, opt_exit }, } }; void menu_print_page (const page_t *page) { - int i; - int cur; + int i, cur; u32 keys, keys_; cur = 0; @@ -102,19 +103,21 @@ void menu_print_page (const page_t *page) if (cur == page->entries_no) cur = 0; } - if (sel_entry->opts_no) { + if (sel_entry->opts_no && (keys_&(KEY_LEFT|KEY_RIGHT))) { if (keys_&KEY_LEFT && *sel_entry->opt_ptr > 0) (*sel_entry->opt_ptr)--; if (keys_&KEY_RIGHT && *sel_entry->opt_ptr < sel_entry->opts_no - 1) (*sel_entry->opt_ptr)++; + if (!sel_entry->confirm && sel_entry->cb) + sel_entry->cb(*sel_entry->opt_ptr); } - if (keys&KEY_A) { - if (sel_entry->cb && sel_entry->cb(*sel_entry->opt_ptr)) - return; + if (keys&KEY_A && sel_entry->confirm && sel_entry->cb) { + sel_entry->cb(*sel_entry->opt_ptr); + return; } - if (keys&KEY_START) + if (keys&KEY_B) return; swiWaitForVBlank(); @@ -124,7 +127,7 @@ void menu_print_page (const page_t *page) void print_msg (const char *msg) { iprintf("\n-- %s\n", msg); - swiDelay(10000000); + swiDelay(50000000); } void pause_menu () { menu_print_page(&paused_pg); } diff --git a/source/video.c b/source/video.c index 6969342..28f8055 100644 --- a/source/video.c +++ b/source/video.c @@ -1,5 +1,6 @@ #include #include +#include "emu.h" #include "mem.h" const u8 apple_font[] = { @@ -240,6 +241,73 @@ static void draw_hires_line_color (u16 *__restrict map, u8 *__restrict ptr) } +static void draw_hires_line_color_ (u16 *__restrict map, u8 *__restrict ptr) ITCM_CODE; +static void draw_hires_line_color_ (u16 *__restrict map, u8 *__restrict ptr) +{ + static const u8 lut[]={ + // even + // msb low + 0, 0, 3, 15, + 0, 12, 15, 15, + // msb high + 0, 0, 6, 15, + 0, 9, 15, 15, + // odd + // msb low + 0, 0, 12, 15, + 0, 3, 15, 15, + // msb high + 0, 0, 9, 15, + 0, 6, 15, 15 + }; + int j, k; + u16 window, msb; + + // Three-bit sliding window + // Based off infos from + // http://www.kreativekorp.com/miscpages/a2info/stdhires.shtml + for (window = j = 0; j < 280/14; j++) { + const u8 b1 = *ptr++; + const u8 b2 = *ptr++; + const u8 b3 = *ptr; + + window |= (b3&1)<<15 | (b2&0x7f)<<8 | (b1&0x7f)<<1; + + // Replicate the msb of b1 and b2 7 times + asm volatile ( + "mov %0,#0;" + "tst %1,#0x80;" + "movne %0,#0x7f;" + "tst %2,#0x80;" + "orrne %0,#(0x7f<<7);" + : "=&r"(msb) + : "r"(b1), "r"(b2) + : + ); + + for (k = 0; k < 7; k++) { + asm volatile ( + "movs %1,%1,lsr #1;" + "and r1,%2,#7;" + "addcs r1,#8;" + "lsr %2,#1;" + "ldrb r0,[%3,r1];" + "movs %1,%1,lsr #1;" + "and r1,%2,#7;" + "add r1,#16;" + "addcs r1,#8;" + "lsr %2,#1;" + "ldrb r2,[%3,r1];" + "orr r0, r2, lsl #8;" + "strh r0,[%0],#2;" + : "+r"(map) + : "r"(msb), "r"(window), "r"(lut) + : "r0", "r1", "r2" + ); + } + } +} + static void draw_hires_scr (u16 *map) ITCM_CODE; static void draw_hires_scr (u16 *__restrict map) { @@ -323,6 +391,9 @@ void video_set_hires (int renderer) case 1: draw_hires_line = draw_hires_line_color; break; + case 2: + draw_hires_line = draw_hires_line_color_; + break; } } @@ -373,12 +444,12 @@ void video_init () // BG2 outside WIN_OUT = 0x4; - video_set_hires(-1); + video_set_hires(emu_hires); memcpy(BG_PALETTE, palette, sizeof(palette)); struct UnpackStruct unpack_bit; - unpack_bit.dataOffset = 14; + unpack_bit.dataOffset = 11; unpack_bit.destWidth = 8; unpack_bit.sourceSize = 64*8; unpack_bit.sourceWidth = 1;