commit 9c0187a8270798f445116151568444141a121afc Author: Astoria Date: Sat Jan 14 21:50:15 2023 -0600 first commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3ae75c0 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +INCLUDE=-I./include -I/usr/include/SDL +LIBS=-lm -lSDL + +CC=gcc-4.6 -s -O2 -fomit-frame-pointer -Wall + +COMMON_HEADERS=include/emuversion.h include/debug.h include/video/colors.h +ALL=emu65el02 + +all: $(ALL) + +release: $(ALL) + +emu65el02: emu65el02.o src/emubase.o src/memory/memory.o src/video/gbuffer.o src/debug.o src/cpu/65el02.o src/display/display.o src/drive/drive.o src/options.o src/monitor.o src/calc.o src/screen.o + $(CC) $^ -o $@ $(LIBS) + +%.o: %.c $(COMMON_HEADERS) + +.c.o: + $(CC) $(INCLUDE) -c $< -o $@ + +clean: + rm -f *~ *.o core *.stackdump src/*.o + /bin/find ./src -iname '*.o' -exec rm {} \; + +distclean: + rm -f *~ *.o core *.stackdump emu65el02.exe + /bin/find ./src -iname '*.o' -exec rm {} \; diff --git a/Makefile.mac b/Makefile.mac new file mode 100644 index 0000000..9a2f883 --- /dev/null +++ b/Makefile.mac @@ -0,0 +1,32 @@ +INCLUDE=-I./include -I/Library/Frameworks/SDL.framework/Versions/A/Headers +LIBS=-lm -framework SDL -framework Cocoa + +CC=gcc -s -O2 -fomit-frame-pointer + +COMMON_HEADERS=include/emuversion.h include/debug.h include/video/colors.h +ALL=emu65el02 + +all: $(ALL) + +release: $(ALL) + +emu65el02: emu65el02.o src/SDLMain.o src/emubase.o src/memory/memory.o src/video/gbuffer.o src/debug.o src/cpu/65el02.o src/display/display.o src/drive/drive.o src/options.o src/monitor.o src/calc.o src/screen.o + $(CC) $^ -o $@ $(LIBS) + +%.o: %.c $(COMMON_HEADERS) + +.c.o: + $(CC) $(INCLUDE) -c $< -o $@ + +%.o: %.m $(COMMON_HEADERS) + +.m.o: + $(CC) $(INCLUDE) -c $< -o $@ + +clean: + rm -f *~ *.o core *.stackdump src/*.o + /bin/find ./src -iname '*.o' -exec rm {} \; + +distclean: + rm -f *~ *.o core *.stackdump emu65el02.exe + /bin/find ./src -iname '*.o' -exec rm {} \; diff --git a/Makefile.mingw b/Makefile.mingw new file mode 100644 index 0000000..deeba3e --- /dev/null +++ b/Makefile.mingw @@ -0,0 +1,27 @@ +INCLUDE=-I./include -I/usr/i686-pc-mingw32/sys-root/mingw/include/SDL -D_GNU_SOURCE=1 -Dmain=SDL_main +LIBS=-lm -lmingw32 -lSDLmain -lSDL.dll -mwindows + +CC=i686-pc-mingw32-gcc-4.5.2 -s -O2 -fomit-frame-pointer + +COMMON_HEADERS=include/emuversion.h include/debug.h include/video/colors.h +ALL=emu65el02 + +all: $(ALL) + +release: $(ALL) + +emu65el02: emu65el02.o src/emubase.o src/memory/memory.o src/video/gbuffer.o src/debug.o src/cpu/65el02.o src/display/display.o src/drive/drive.o src/options.o src/monitor.o src/calc.o src/screen.o + $(CC) $^ -o $@ $(LIBS) + +%.o: %.c $(COMMON_HEADERS) + +.c.o: + $(CC) $(INCLUDE) -c $< -o $@ + +clean: + rm -f *~ *.o core *.stackdump src/*.o + /bin/find ./src -iname '*.o' -exec rm {} \; + +distclean: + rm -f *~ *.o core *.stackdump emu65el02.exe + /bin/find ./src -iname '*.o' -exec rm {} \; diff --git a/docs/65el02_instructions.txt b/docs/65el02_instructions.txt new file mode 100644 index 0000000..6c14bd5 --- /dev/null +++ b/docs/65el02_instructions.txt @@ -0,0 +1,159 @@ +New registers: + I - Index, used by some of the new instructions + D - Used by the math extension as the higher 16-bit of the 32-bit value (multiply / divide). + +NXT ($02) - NExT word + PC = (I), I = I + 2 + 8-bit mode example: + lda (regI) + sta ptr + lda (regI+1) + sta ptr+1 + inc regI + inc regI + jmp (ptr) + + +ENT ($22) - Enter word + RHI, I = PC + 2, PC = (PC) + +NXA ($42) - NeXt byte/word to Accumlator + A = (I), if M=0 then I = I + 1 else I = I + 2 + example: + lda (regI) ; 16-bit word when M flag is set + inc regI + .if flagM=1 + inc regI + .fi + + +TXI ($5c) - Transfer X to I + regI = regX + N,Z flags updated + + +TIX ($dc) - Transfer I to X + regX = regI + N,Z flags affected + + +RER ($82) - push effective RElative address to R stack + (R) = ( PC + value ) >> 8 + (R - 1) = ( PC + value ) & 0xff + R = R - 2 + + This function works like the branches but instead of setting PC it push the result in the R stack + +REA ($44) - push address to R stack + (R) = value >> 8 + (R - 1) = value & 0xff + R = R - 2 + + This functions simply puts the value to R stack + + 8-bit mode example: + lda #>value + sta (regR) + dec regR + lda #> 8 + (R - 1) = (value+1) & 0xff + R = R - 2 + + Works like the previous instruction but address came from indirected zero page address + + 8-bit mode example: + lda (value) + sta (regR) + dec regR + inc value + lda (value) + sta (regR) + dec regR + +RHI ($0b) - push I register to R stack + (R) = I >> 8 + (R - 1) = I & 0xff + R = R - 2 + + example: + lda I + sta (regR) + dec regR + lda I+1 + sta (regR) + dec regR + +RLI ($2b) - pull I register from R stack + the opposite of RHI + +RHA ($4b) - push A register to R stack + Depends on flagM, instruction like PHA + +RLA ($6b) - pull A register from R stack + Depends on flagM, instruction like PLA + +RHX ($1b) - push X register to R stack + Depends on flagX, instruction like PHX + +RLX ($3b) - pull X register from R stack + Depends on flagX, instruction like PLX + +RHY ($5b) - push y register to R stack + Depends on flagX, instruction like PHY + +RLY ($7b) - pull y register from R stack + Depends on flagX, instruction like PLY + +TXR ($8b) - Transfer X to R + if flagX = 0 then R = X + + SP messed up if flagX = 1, SP = R & 0xff | X & 0xff + +TRX ($ab) - Transfer R to X + X = R + N,Z flags affected + +TXI ($5c) - Transfer X to I + I = X + N,Z flags affected + +TIX ($dc) - Transfer I to X + X = I + N,Z flags affected + +ORA, AND, EOR, ADC, STA, LDA, CMP, SBC + Works like the standard 65816 r,S and (r,S),Y instructions just using R instead of S + +MUL - signed (c=0) or unsigned (c=1) MULltiply (16-bit * 16-bit) + supports BCD mode + +DIV - signed (c=0) or unsigned (c=1) DIVide (32-bit / 16-bit) + supports BCD mode + +ZEA - zero extend A / clear D + D = 0 +SEA - signed extend A + if the highest bit of A is set then D = 0xffff else D = 0 + +TAD - Transfer A to D + D = A + N,Z flags affected + +TDA - Transfer D to A + A = D + N,Z flags affected + +PHD - PusH D to stack + +PLD - PulL D from stack + + +Known bugs: + - Stack pointers wrong (TSX,TXS) comparing it to a real 65xx based cpu + - the default SP is $0200 instead of $01ff + diff --git a/docs/changelog.txt b/docs/changelog.txt new file mode 100644 index 0000000..15dd2fd --- /dev/null +++ b/docs/changelog.txt @@ -0,0 +1,127 @@ +0.12: (20120819) + - Fancy dialogs for tweaking emulator options and peripherals. Built-in help is not finished yet. + - New peripheral handling to support multiple monitors/drives/io extenders + - Option for cpu speed throttle (1x, 2x, 5x, 10x, 100x) + - Option for drive speed boost + - Settings load and save + - 16 COLOR MONITOR + i've added a 16 color monitor to the emulator; same as the monochrome monitor, but with attributes + + same registers as the monochrome except + attributes line buffer from 0x60->0xaf + format: xxxx yyyy + xxxx = background color (0 bits in character rom) + yyyy = foreground color (1 bits in character rom) + + monitor type @ 0xff = 1 (monochrome should be 0 as is now) + + blitter + blitter enhancements required for the 16 color monitor + blit mode 0x07: + 0x1: almost the same, attribute value @ 0x09 + 0x2: remains the same (invert) + 0x3: shift also shift attributes + + colors + matches the commodore-64 color table: http://en.wikipedia.org/wiki/List_of_8-bit_computer_hardware_palettes#C-64 + + + examples + in pseudo-C terms, you set color like this: + // select row first as normal, then do: + poke (0x360+$column, (bgcol << 4) | (fgcol & 0xf)) + + forth example (by BloodyRain2k) + HEX : colors 30 0 DO I 300 C! 30 0 DO J 3 / 10 * I 3 / + 360 I + C! LOOP LOOP ; + + tetris.img (with colors :) and colordemo.img available within the archive. + +0.11: (20120809) + Minor changes in keyboard handling + - key typing works even if emulation is not in running state + - you can use F6 to access built-in monitor as pause/break key not exists + on some systems + - probably now not US keyboards works well (like altgr+q) + +0.10: (20120808) + changes in debugger / built-in monitor / cpu-core + - multiple breakpoints (maximum 32) + - label support + + new command line parameter: + -l=file.name reads 64tass labels file for easier debugging + +0.09: (20120528) + Emulation is now almost as identical as the ingame computer + - machine code monitor available with PAUSE key (pretty limited at the moment) + - IO Expanders emulated, set and check status in monitor with "io" command + - RedBus device switch now causes delay + +0.08: (20120525) + with Eloraam's permission the CPU emulation is not issue anymore + - image handling fix in drive code + - minor debug fixes + +0.07: (20120521) + new command line parameters: + -nospbug enables fix/workaround for SP handling bug in 65el02 + + minor debug screen changes + +0.06: (20120521) + WARNING: CPU core changed so probably you need to change your programs + + updated due to new RedPower release (RedPower Control 2pre5b2) + - replaced redforth.img (MineOS 1.1) + - replaced rpcboot.bin (CPU loader no longer crashes when loading from a disk >64k) + + here's the changes what Eloraam made and implemented into the emulator + (however unsigned div/mul not tested yet): + - CPU: Fixed interpretation of the E flag + - CPU: C and Z flags are no longer swapped + - CPU: Fixed the carry flag for SBC + - CPU: Add unsigned divide support (C=0), fix divide bugs + - CPU: Added unsigned multiply support (C=0) + + command line parameter "-nobug" removed as the SBC bug is fixed + +0.05: (20120519) + new command line parameters: + -s start emulation immediately (no f9 pressing required) + -nobug fix the sbc bug which presents in RedPower Control 2pre5b1 + +0.04: (20120509) + emulator now uses SDL, hopefully this makes porting easier + blitter and drive handling separated. (no more immediately blitter updates and disk answers) + keyboard handling changed + screen cache bugfix (no blinking and stucked cursor) + + drive handling updated + - read/write sector working as expected + - diskid, read and set diskname uses the name of the image (or "System Disk" on default "redforth.img") + - default "redforth.img" moved to roms folder + + debug changes + - $xx,R and $xx,S codesize calculation and printout was wrong + + +0.03: (20120505) + mostly blitter fix. looks like finally works as expected + cygwin doesn't need anymore (or at least i hope so) + +0.02: (20120505) + debug changes + - opcode and addressing mode fixes + - some status displaying + - default image name is "redforth.img" if no parameter given + + working blitter + - redforth not hangs on PAGE anymore + + new parameters: + -b=value set breakpoint to value + -pc=value set reset PC to value (default $0400) + -s start emulation immediately (no f9 pressing required) + +0.01: (20120504) + initial release \ No newline at end of file diff --git a/docs/mcfs_format.txt b/docs/mcfs_format.txt new file mode 100644 index 0000000..d927686 --- /dev/null +++ b/docs/mcfs_format.txt @@ -0,0 +1,127 @@ + MineCraft FileSystem (MCFS) documentation + + + Disk format + +Each floppy disk capacity is limited to 2048 sectors by the disk drive. +Each sector is 128 bytes long so the maximum physical capacity of a disk +is 256 kilobytes. An MCFS formatted disk can hold (2048-16)*126 bytes +(250 kilobytes) of user data. + + Sector Description + 0 - 3 MCFS boot loader + 4 - 5 Sector allocation map (2048 bits, one bit / sector) + 6 - 15 Directory (4 entries / sector, maximum 40 entries) +16 - 2047 Available for files + + + + Boot loader + +This small loader only job is to load the bootable programs which are +then executed. The boot loaders remaps itself after the execution into the +two stack area at $0100 and $0200 which makes possible to load the program +from $0500 like the original RPC8/e boot code does. + +Most of the possible cases are handled and visible during the boot sequence, +these are the following: +- detects drive errors during the boot (for example: destroyed cable) +- handles read errors (for example: a truncated disk image) +- detects available memory and display and error message when a programs + doesn't fit into the memory. +- warns if disk is not bootable + +Sector Byte + 0-3 0-511 Boot loader which is loaded to memory and started at + address $0500 + + 0 122-123 Starting sector of the bootable file. + If sector = 0 then the disk is not bootable. + + 0 124-127 MCFS magic constant: $4d $43 $46 $53 "MCFS" + + + + Sector allocation map + +Sector allocation map (SAM) is a plain bitmap for each physical sector. +Bitmap is linear, however the least significant bit is on the left + +Sector Byte Content + 4 0 SAM for sector 0-7 + Example: the byte value is $a5 so the sector availability + looks like this: + + 2^7 6 5 4 3 2 1 0 + ------------------- + 1 0 1 0 0 1 0 1 + + sector: 0 1 2 3 4 5 6 7 + + in this case sector 0,2,5 and 7 is occupied and sector + 1,3,4,6 is available. + + 4 1 SAM for sector 8-15 + 4 2 SAM for sector 15-23 + ... ... + 4 127 SAM for sector 1016-1023 + 5 0 SAM for sector 1024-1031 + 5 1 SAM for sector 1032-1039 + ... ... + 5 126 SAM for sector 2032-2039 + 5 127 SAM for sector 2040-2047 + + + Directory structure + +The first entry of a directory structure is the header which contains the name +of the disk. Each entry is 32 bytes long, the maximum length of a filename +is 28. Each sector is 128 bytes long so 4 entries fits into one sector. +10 sectors are available for directory entries so the maximum capacity is 39 +files plus the header (40 in total). + +Sector Byte Content + 6 0- 3 Unused + 6 4-31 Disk name. all characters MSB is set to 1 ($80) + + 6 32-63 Directory entry #1 + 6 32-33 Starting sector of the file. + If sector = 0 the directory entry is free. + 6 34-35 Size of the file in sectors + 6 36-63 File name + + 6 64-95 Directory entry #2 + 6 64-65 Starting sector of the file. + If sector = 0 the directory entry is free. + 6 66-67 Size of the file in sectors + 6 68-95 File name + + ... ... + + 15 96-127 Directory entry #39 + 15 96- 97 Starting sector of the file. + If sector = 0 the directory entry is free. + 15 98- 99 Size of the file in sectors + 15 100-127 File name + + + File format + +First two bytes of each sector were used as a pointer to the next sector +of the file, so only 126 out of the 128 bytes of a sector were used for file +contents. In the last sector of a file the higher value of a pointer is set +to $ff and the lower value of the pointer holds the remaining bytes used on +the actual sector. + +Sector Byte + xx 0-1 Pointer to next sector #yy (word) + If byte 1 is $ff then the number of bytes which used + within the sector is contained in byte 0. + xx 2-127 User data + + yy 0-1 Pointer to next sector #zz (word) + If byte 1 is $ff then the number of bytes which used + within the sector is contained in byte 0. + yy 2-127 User data + + zz ... diff --git a/docs/readme.txt b/docs/readme.txt new file mode 100644 index 0000000..8364116 --- /dev/null +++ b/docs/readme.txt @@ -0,0 +1,43 @@ +BiGFooT's 65el02 emulator v0.12 + +With Eloraam's permission, for enhanced compatibility +the CPU emulation is based partly on RedPower. + +Feel free to contact me if you have any questions or comments. +e-mail: bigfoot _at_ bigfootinformatika _dot_ hu + + +usage: + emu65el02 [parameters] [image.img] + +parameters: + -b=value set breakpoint to value + -pc=value set reset PC to value (default $0400) + -s not start emulation immediately + -m=value set available memory banks (1-8, 8K/each. default value is 1) + -nospbug enables fix/workaround for SP handling bug in 65el02 + -l=file.name reads 64tass labels file for easier debugging + + [image.img] path to disk image file (default value is roms/redforth.img) + + +keys: + f1 - built-in help (not finished yet) + f2 - options + f3 - peripherals + f4 - io extenders + + f9 - start/stop emulation + alt-x + alt-f4 + shift-esc - exit from emulator + f11 - step by step trace + f12 - step over + + pgdown - memory map ptr+$08 + pgup - memory map ptr-$08 + shift-pgdown - memory map ptr+$80 + shift-pgup - memory map ptr-$80 + + f6 + pause - enter to machine code monitor diff --git a/emu65el02.c b/emu65el02.c new file mode 100644 index 0000000..8041737 --- /dev/null +++ b/emu65el02.c @@ -0,0 +1,125 @@ +//--------------------------------------------------------------------------- +//- BiGFooT's 65EL02 Emulator V0.12 ---------------------------- 2012.08.17 - +//--------------------------------------------------------------------------- +#include +#include +#include +#include +//--------------------------------------------------------------------------- +#include "video/gbuffer.h" +#include "drive/drive.h" +#include "calc.h" +//--------------------------------------------------------------------------- +#include "emuversion.h" +#include "emubase.h" +#include "memory/memory.h" +#include "cpu/65el02.h" + +#include "monitor.h" + +#include "SDL/SDL.h" +//--------------------------------------------------------------------------- + +int +main(int argc, char **argv) +{ + char tempstring[512]; + double tempdouble; + + int qi, tempint; + + *defdiskname = 0; + +// stdout is redirected to a text file... +// printf("%s\n%s\n\n",emuversion,eloraam); + + for (qi = 1; qi < argc; qi++) + { + if (*argv[qi] == '-') + { + if (strcmp(argv[qi], "-s") == 0) + { + emulation_run = 0; + } + + if (strcmp(argv[qi], "-nospbug") == 0) + { + nospbug = 1; + } + + if (strncmp(argv[qi], "-pc=", 4) == 0) + { + calc(&argv[qi][4], &tempdouble); + start_pc = (int) tempdouble; + printf("PC at reset: %04X\n", start_pc); + } + + if (strncmp(argv[qi], "-b=", 3) == 0) + { + if (!calc(&argv[qi][3], &tempdouble)) + { + init_breakpoint = (int) tempdouble; + } + else + { + init_breakpoint = getaddress(&argv[qi][3]); + } +// printf("Breakpoint: %04X\n", init_breakpoint); + } + + if (strncmp(argv[qi], "-m=", 3) == 0) + { + calc(&argv[qi][3], &tempdouble); + tempint = (int) tempdouble; + if ((tempint<1) || (tempint>8)) + { + printf("Invalid memory banks %d. Must be between 1 and 8.\n",tempint); + exit(0); + } + else + { + printf("Memory: %dkb\n", tempint << 3); + memory_max = tempint << 13; + } + } + + if (strncmp(argv[qi], "-l=", 3) == 0) + { + monitor_listing(&argv[qi][3]); + } + + } + else + { + if (!*defdiskname) + { + strncpy(defdiskname, argv[qi], sizeof(defdiskname)); + defdisktype = 0; + } + } + } + + if (!*defdiskname) + { + strcpy(defdiskname, "roms/redforth.img"); + defdisktype = 1; + } + + SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO); + SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(250, 25); + + if (startptc(emuversion)) + { + emulation(); + endptc(); + } + else + { + printf("Video initialization failed.\n"); + } + + SDL_Quit(); + + return (0); +} diff --git a/include/SDLMain.h b/include/SDLMain.h new file mode 100644 index 0000000..c56d90c --- /dev/null +++ b/include/SDLMain.h @@ -0,0 +1,16 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#ifndef _SDLMain_h_ +#define _SDLMain_h_ + +#import + +@interface SDLMain : NSObject +@end + +#endif /* _SDLMain_h_ */ diff --git a/include/calc.h b/include/calc.h new file mode 100644 index 0000000..aca2be0 --- /dev/null +++ b/include/calc.h @@ -0,0 +1 @@ +const char* calc(char * kifejezes,double * result); diff --git a/include/cpu/65el02.h b/include/cpu/65el02.h new file mode 100644 index 0000000..a432880 --- /dev/null +++ b/include/cpu/65el02.h @@ -0,0 +1,61 @@ +void coldBootCPU(); +void executeInsn(); + +struct cpustruct +{ + + int addrPOR; + int addrBRK; + int regSP; + int regPC; + int regA; + int regB; + int regX; + int regY; + int regR; + int regI; + int regD; + + unsigned char flagC; + unsigned char flagZ; + unsigned char flagID; + unsigned char flagD; + unsigned char flagBRK; + unsigned char flagO; + unsigned char flagN; + unsigned char flagE; + unsigned char flagM; + unsigned char flagX; + + int mmuRBB; + int mmuRBA; + int mmuRBW; + + unsigned char mmuEnRB; + unsigned char mmuEnRBW; + + int byte0; // = 2; + int byte1; // = 1; + + int cycles; + + int waiTimeout; + int rbTimeout; + int rbCache; + + int breakpoint_count; + int ticks; + int brk; + + int breakpoints[32]; + + int cycles_per_tick; + int mmu_type; + int no_io_penality; + + unsigned char interrupt_waiting[256]; + unsigned char interrupt_type[256]; +}; + +struct cpustruct cpu; +extern int nospbug; diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..3a46cd9 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,122 @@ +void showscreen(char *screen, int frame, int cx, int cy, int blink); +void showdebug(); +void showmemory(int memorypos); +int getinst(char *str,int ip); +void showinst(int memorypos,struct cpustruct cpu); + +extern int mempos; + +//--------------------------------------------------------------------------- +//- Debugging datas --------------------------------------------------------- +//--------------------------------------------------------------------------- +static char opcodes[256][4]={ +"brk\0","ora\0","nxt\0","ora\0","tsb\0","ora\0","asl\0","ora\0","php\0","ora\0","asl\0","rhi\0","tsb\0","ora\0","asl\0","mul\0", // 0x00 +"bpl\0","ora\0","ora\0","ora\0","trb\0","ora\0","asl\0","ora\0","clc\0","ora\0","inc\0","rhx\0","trb\0","ora\0","asl\0","mul\0", // 0x10 +"jsr\0","and\0","ent\0","and\0","bit\0","and\0","rol\0","and\0","plp\0","and\0","rol\0","rli\0","bit\0","and\0","rol\0","mul\0", // 0x20 +"bmi\0","and\0","and\0","and\0","bit\0","and\0","rol\0","and\0","sec\0","and\0","dec\0","rlx\0","bit\0","and\0","rol\0","mul\0", // 0x30 +"rti\0","eor\0","nxa\0","eor\0","rea\0","eor\0","lsr\0","eor\0","pha\0","eor\0","lsr\0","rha\0","jmp\0","eor\0","lsr\0","div\0", // 0x40 +"bvc\0","eor\0","eor\0","eor\0","rei\0","eor\0","lsr\0","eor\0","cli\0","eor\0","phy\0","rhy\0","txi\0","eor\0","lsr\0","div\0", // 0x50 +"rts\0","adc\0","per\0","adc\0","stz\0","adc\0","ror\0","adc\0","pla\0","adc\0","ror\0","rla\0","jmp\0","adc\0","ror\0","div\0", // 0x60 +"bvs\0","adc\0","adc\0","adc\0","stz\0","adc\0","ror\0","adc\0","sei\0","adc\0","ply\0","rly\0","jmp\0","adc\0","ror\0","div\0", // 0x70 +"bra\0","sta\0","rer\0","sta\0","sty\0","sta\0","stx\0","sta\0","dey\0","bit\0","txa\0","txr\0","sty\0","sta\0","stx\0","zea\0", // 0x80 +"bcc\0","sta\0","sta\0","sta\0","sty\0","sta\0","stx\0","sta\0","tya\0","sta\0","txs\0","txy\0","stz\0","sta\0","stz\0","sea\0", // 0x90 +"ldy\0","lda\0","ldx\0","lda\0","ldy\0","lda\0","ldx\0","lda\0","tay\0","lda\0","tax\0","trx\0","ldy\0","lda\0","ldx\0","tda\0", // 0xa0 +"bcs\0","lda\0","lda\0","lda\0","ldy\0","lda\0","ldx\0","lda\0","clv\0","lda\0","tsx\0","tyx\0","ldy\0","lda\0","ldx\0","tad\0", // 0xb0 +"cpy\0","cmp\0","rep\0","cmp\0","cpy\0","cmp\0","dec\0","cmp\0","iny\0","cmp\0","dex\0","wai\0","cpy\0","cmp\0","dec\0","pld\0", // 0xc0 +"bne\0","cmp\0","cmp\0","cmp\0","pei\0","cmp\0","dec\0","cmp\0","cld\0","cmp\0","phx\0","stp\0","tix\0","cmp\0","dec\0","phd\0", // 0xd0 +"cpx\0","sbc\0","sep\0","sbc\0","cpx\0","sbc\0","inc\0","sbc\0","inx\0","sbc\0","nop\0","xba\0","cpx\0","sbc\0","inc\0","mmu\0", // 0xe0 +"beq\0","sbc\0","sbc\0","sbc\0","pea\0","sbc\0","inc\0","sbc\0","sed\0","sbc\0","plx\0","xce\0","jsr\0","sbc\0","inc\0","???\0"}; + +/* 0 - nothing + 1 - ix ($xx,x) + 2 - zp $xx + 3 - abs $xxyy + 4 - iy ($xx),y + 5 - zpx $xx,x + 6 - aby $xxyy,y + 7 - abx $xxyy,x + 8 - rel +-127 + 9 - ind ($xxyy) + 10 - zpy $xx,y + 11 - dir #$xx + 12 - ajm $xxxx + 13 - abs $xx,s + 14 - isy ($xx,s),y + 15 - zp ($xx) + 16 - abs $xx,r + 17 - isy ($xx,r),y + 18 - dir #$xxyy +*/ + +static char codesizetable[]= + {1,2,2,3,2,2,3,3,2,3,2,2,3,2,2,2,2,2,3}; + +static char addrmode[4][256]={ +{ + 0,1, 0, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 2, // 0x00 + 8,4,15, 14, 2,5, 5,17,0, 6,0,0, 3,7,7, 5, // 0x10 + 12,1, 0, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 3, // 0x20 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x30 + 0,1, 0, 13, 3,2, 2,16,0,18,0,0,12,3,3, 2, // 0x40 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 5, // 0x50 + 0,1, 8, 13, 2,2, 2,16,0,18,0,0, 9,3,3, 3, // 0x60 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x70 + 8,1, 8, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 0, // 0x80 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 3,7,7, 0, // 0x90 + 18,1,18, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 0, // 0xa0 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 7,7,6, 0, // 0xb0 + 18,1,11, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 0, // 0xc0 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 0, // 0xd0 + 18,1,11, 13, 2,2, 2,16,0,18,0,0, 3,3,3,11, // 0xe0 + 8,4,15, 14, 3,5, 5,17,0, 6,0,0, 3,7,7, 0}, // 0xf0 +{ + 0,1, 0, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 2, // 0x00 + 8,4,15, 14, 2,5, 5,17,0, 6,0,0, 3,7,7, 5, // 0x10 + 12,1, 0, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 3, // 0x20 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x30 + 0,1, 0, 13, 3,2, 2,16,0,11,0,0,12,3,3, 2, // 0x40 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 5, // 0x50 + 0,1, 8, 13, 2,2, 2,16,0,11,0,0, 9,3,3, 3, // 0x60 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x70 + 8,1, 8, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 0, // 0x80 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 3,7,7, 0, // 0x90 + 11,1,11, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 0, // 0xa0 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 7,7,6, 0, // 0xb0 + 11,1,11, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 0, // 0xc0 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 0, // 0xd0 + 11,1,11, 13, 2,2, 2,16,0,11,0,0, 3,3,3,11, // 0xe0 + 8,4,15, 14, 3,5, 5,17,0, 6,0,0, 3,7,7, 0}, // 0xf0 +{ + 0,1, 0, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 2, // 0x00 + 8,4,15, 14, 2,5, 5,17,0, 6,0,0, 3,7,7, 5, // 0x10 + 12,1, 0, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 3, // 0x20 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x30 + 0,1, 0, 13, 3,2, 2,16,0,18,0,0,12,3,3, 2, // 0x40 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 5, // 0x50 + 0,1, 8, 13, 2,2, 2,16,0,18,0,0, 9,3,3, 3, // 0x60 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x70 + 8,1, 8, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 0, // 0x80 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 3,7,7, 0, // 0x90 + 18,1,18, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 0, // 0xa0 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 7,7,6, 0, // 0xb0 + 18,1,11, 13, 2,2, 2,16,0,18,0,0, 3,3,3, 0, // 0xc0 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 0, // 0xd0 + 18,1,11, 13, 2,2, 2,16,0,18,0,0, 3,3,3,11, // 0xe0 + 8,4,15, 14, 3,5, 5,17,0, 6,0,0, 3,7,7, 0}, // 0xf0 +{ + 0,1, 0, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 2, // 0x00 + 8,4,15, 14, 2,5, 5,17,0, 6,0,0, 3,7,7, 5, // 0x10 + 12,1, 0, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 3, // 0x20 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x30 + 0,1, 0, 13, 3,2, 2,16,0,11,0,0,12,3,3, 2, // 0x40 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 5, // 0x50 + 0,1, 8, 13, 2,2, 2,16,0,11,0,0, 9,3,3, 3, // 0x60 + 8,4,15, 14, 5,5, 5,17,0, 6,0,0, 3,7,7, 7, // 0x70 + 8,1, 8, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 0, // 0x80 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 3,7,7, 0, // 0x90 + 11,1,11, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 0, // 0xa0 + 8,4,15, 14, 5,5,10,17,0, 6,0,0, 7,7,6, 0, // 0xb0 + 11,1,11, 13, 2,2, 2,16,0,11,0,0, 3,3,3, 0, // 0xc0 + 8,4,15, 14,15,5, 5,17,0, 6,0,0, 0,7,7, 0, // 0xd0 + 11,1,11, 13, 2,2, 2,16,0,11,0,0, 3,3,3,11, // 0xe0 + 8,4,15, 14, 3,5, 5,17,0, 6,0,0, 3,7,7, 0}}; // 0xf0 diff --git a/include/display/display.h b/include/display/display.h new file mode 100644 index 0000000..c2fc5e3 --- /dev/null +++ b/include/display/display.h @@ -0,0 +1,20 @@ +#ifndef _BLITTER_H_ +#define _BLITTER_H_ + +#define MAX_DISPLAY 256 + +typedef struct { + unsigned char regs[0x10]; + unsigned char kbbuf[0x10]; + unsigned char type; +} displaystruct; + +displaystruct displays[MAX_DISPLAY]; + +void blitter(int id); +void init_displays(); +void disp_store(int id, int ptr, unsigned char value); +unsigned char disp_load(int id, int ptr); +unsigned char disp_key(int id, unsigned char ch); + +#endif diff --git a/include/drive/drive.h b/include/drive/drive.h new file mode 100644 index 0000000..6e8d4ee --- /dev/null +++ b/include/drive/drive.h @@ -0,0 +1,24 @@ + +typedef struct +{ + unsigned char buffer[0x80]; + unsigned int sector; + unsigned char command; + + char *name; + unsigned char serial[16]; + int type; + +} drivestruct; + +drivestruct drives[256]; + +char defdiskname[256]; +char defdisktype; + +extern int drive_io_penality; + +void drive(); +void drive_store(int id, int ptr, unsigned char value); +unsigned char drive_load(int id, int ptr); +void drive_type(int id, int type); diff --git a/include/emu65el02.h b/include/emu65el02.h new file mode 100644 index 0000000..0aafe09 --- /dev/null +++ b/include/emu65el02.h @@ -0,0 +1,151 @@ +//--------------------------------------------------------------------------- +extern struct CPU_Regs cpu; +//--------------------------------------------------------------------------- +//extern char CPU_emul(struct CPU_Regs cpu); + +extern void CIA_emul(); +extern void VIC_emul(); + +extern void CIA_Reset(); +extern void VIC_Reset(); +extern void SID_Reset(); +extern void CPU_Reset(); + +extern void C64_Reset(); + +extern void SID_Create(); +extern unsigned int SID_calc_buffer(); + +extern void VIC_Recalcdatas(); +//--------------------------------------------------------------------------- +static int start_pc=-1; +static int init_breakpoint=-1; +//--------------------------------------------------------------------------- +static char emulation_run=0; +//--------------------------------------------------------------------------- +//- Debugging datas --------------------------------------------------------- +//--------------------------------------------------------------------------- +static char opcodes[256][4]={ +"brk\0","ora\0","???\0","???\0","???\0","ora\0","asl\0","???\0","php\0","ora\0","asl\0","???\0","NOP\0","ora\0","asl\0","???\0", // 0x00 +"bpl\0","ora\0","???\0","???\0","???\0","ora\0","asl\0","???\0","clc\0","ora\0","NOP\0","???\0","NOP\0","ora\0","asl\0","???\0", // 0x10 +"jsr\0","and\0","???\0","???\0","bit\0","and\0","rol\0","???\0","plp\0","and\0","rol\0","???\0","bit\0","and\0","rol\0","???\0", // 0x20 +"bmi\0","and\0","???\0","???\0","???\0","and\0","rol\0","???\0","sec\0","and\0","NOP\0","???\0","NOP\0","and\0","rol\0","???\0", // 0x30 +"rti\0","eor\0","???\0","???\0","???\0","eor\0","lsr\0","???\0","pha\0","eor\0","lsr\0","???\0","jmp\0","eor\0","lsr\0","???\0", // 0x40 +"bvc\0","eor\0","???\0","???\0","???\0","eor\0","lsr\0","???\0","cli\0","eor\0","NOP\0","???\0","NOP\0","eor\0","lsr\0","???\0", // 0x50 +"rts\0","adc\0","???\0","???\0","???\0","adc\0","ror\0","???\0","pla\0","adc\0","ror\0","???\0","jmp\0","adc\0","ror\0","???\0", // 0x60 +"bvs\0","adc\0","???\0","???\0","???\0","adc\0","ror\0","???\0","sei\0","adc\0","NOP\0","???\0","NOP\0","adc\0","ror\0","???\0", // 0x70 +"???\0","sta\0","???\0","???\0","sty\0","sta\0","stx\0","???\0","dey\0","???\0","txa\0","???\0","sty\0","sta\0","stx\0","AXS\0", // 0x80 +"bcc\0","sta\0","???\0","???\0","sty\0","sta\0","stx\0","???\0","tya\0","sta\0","txs\0","???\0","???\0","sta\0","???\0","???\0", // 0x90 +"ldy\0","lda\0","ldx\0","LDT\0","ldy\0","lda\0","ldx\0","LDT\0","tay\0","lda\0","tax\0","???\0","ldy\0","lda\0","ldx\0","LDT\0", // 0xa0 +"bcs\0","lda\0","???\0","LDT\0","ldy\0","lda\0","ldx\0","LDT\0","clv\0","lda\0","tsx\0","???\0","ldy\0","lda\0","ldx\0","LDT\0", // 0xb0 +"cpy\0","cmp\0","???\0","???\0","cpy\0","cmp\0","dec\0","DCP\0","iny\0","cmp\0","dex\0","???\0","cpy\0","cmp\0","dec\0","DCP\0", // 0xc0 +"bne\0","cmp\0","???\0","???\0","???\0","cmp\0","dec\0","???\0","cld\0","cmp\0","NOP\0","???\0","NOP\0","cmp\0","dec\0","???\0", // 0xd0 +"cpx\0","sbc\0","???\0","???\0","cpx\0","sbc\0","inc\0","???\0","inx\0","sbc\0","nop\0","???\0","cpx\0","sbc\0","inc\0","???\0", // 0xe0 +"beq\0","sbc\0","???\0","ISB\0","???\0","sbc\0","inc\0","???\0","sed\0","sbc\0","NOP\0","???\0","NOP\0","sbc\0","inc\0","???\0"}; + +static char codesizetable[256]={ + 1,2,1,1,1,2,2,1,1,2,1,1,3,3,3,1, // 0x00 + 2,2,1,1,1,2,2,1,1,3,1,1,3,3,3,1, // 0x10 + 3,2,1,1,2,2,2,1,1,2,1,1,3,3,3,1, // 0x20 + 2,2,1,1,1,2,2,1,1,3,1,1,3,3,3,1, // 0x30 + 1,2,1,1,1,2,2,1,1,2,1,1,3,3,3,1, // 0x40 + 2,2,1,1,1,2,2,1,1,3,1,1,3,3,3,1, // 0x50 + 1,2,1,1,1,2,2,1,1,2,1,1,3,3,3,1, // 0x60 + 2,2,1,1,1,2,2,1,1,3,1,1,3,3,3,1, // 0x70 + 1,2,1,1,2,2,2,1,1,1,1,1,3,3,3,3, // 0x80 + 2,2,1,1,2,2,2,1,1,3,1,1,1,3,1,1, // 0x90 + 2,2,2,2,2,2,2,2,1,2,1,1,3,3,3,3, // 0xa0 + 2,2,1,2,2,2,2,2,1,3,1,1,3,3,3,3, // 0xb0 + 2,2,1,1,2,2,2,2,1,2,1,1,3,3,3,3, // 0xc0 + 2,2,1,1,1,2,2,1,1,3,1,1,3,3,3,1, // 0xd0 + 2,2,1,1,2,2,2,1,1,2,1,1,3,3,3,1, // 0xe0 + 2,2,1,3,1,2,2,1,1,3,1,1,3,3,3,1}; + + +/* 0 - nothin' + 1 - ix ($xx,x) + 2 - np $xx + 3 - abs $xxyy + 4 - iy ($xx),y + 5 - npx $xx,x + 6 - aby $xxyy,y + 7 - abx $xxyy,x + 8 - rel +-127 + 9 - ind ($xxyy) + 10 - npy $xx,y + 11 - dir #$xx + 12 - ajm $xxxx */ + +static char addrmode[256]={ + 0,1, 0, 0,0,2, 2, 0,0,11,0,0, 3,3,3,0, // 0x00 + 8,4, 0, 0,0,5, 5, 0,0, 6,0,0, 3,7,7,0, // 0x10 + 12,1, 0, 0,2,2, 2, 0,0,11,0,0, 3,3,3,0, // 0x20 + 8,4, 0, 0,0,5, 5, 0,0, 6,0,0, 3,7,7,0, // 0x30 + 0,1, 0, 0,0,2, 2, 0,0,11,0,0,12,3,3,0, // 0x40 + 8,4, 0, 0,0,5, 5, 0,0, 6,0,0, 3,7,7,0, // 0x50 + 0,1, 0, 0,0,2, 2, 0,0,11,0,0, 9,3,3,0, // 0x60 + 8,4, 0, 0,0,5, 5, 0,0, 6,0,0, 3,7,7,0, // 0x70 + 0,1, 0, 0,2,2, 2, 0,0, 0,0,0, 3,3,3,3, // 0x80 + 8,4, 0, 0,5,5,10, 0,0, 6,0,0, 0,7,0,0, // 0x90 + 11,1,11, 1,2,2, 2, 2,0,11,0,0, 3,3,3,3, // 0xa0 + 8,4, 0, 4,5,5,10,10,0, 6,0,0, 7,7,6,6, // 0xb0 + 11,1, 0, 0,2,2, 2, 2,0,11,0,0, 3,3,3,3, // 0xc0 + 8,4, 0, 0,0,5, 5, 0,0, 6,0,0, 3,7,7,0, // 0xd0 + 11,1, 0, 0,2,2, 2, 0,0,11,0,0, 3,3,3,0, // 0xe0 + 8,4, 0, 0,0,5, 5, 0,0, 6,0,0, 3,7,7,0}; // 0xf0 + +static unsigned char keycodes_normal[256]={ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x13, 0x9d, 0x91, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x3b, 0x00, 0x3d, 0x00, 0x00, + 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x2d, 0x2c, 0x2b, 0x2e, 0x2f, + 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x3d, 0x2a, 0x3b, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char keycodes_shifted[256]={ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x93, 0x9d, 0x91, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x7d, 0x3c, 0x7b, 0x3e, 0x3f, + 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x60, 0x5d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char keyb_rowcol[256]={ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x72, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, + 0x17, 0x75, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, 0xff, + 0x74, 0xff, 0xff, 0xff, 0x63, 0x02, 0x07, 0x02, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x43, 0x70, 0x73, 0x10, 0x13, 0x20, 0x23, 0x30, 0x33, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x12, 0x34, 0x24, 0x22, 0x16, 0x25, 0x32, 0x35, 0x41, 0x42, 0x45, 0x52, 0x44, 0x47, 0x46, + 0x51, 0x76, 0x21, 0x15, 0x26, 0x36, 0x37, 0x11, 0x27, 0x31, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x55, 0x53, 0x57, 0x50, 0x54, 0x67, + 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x56, 0x65, 0x61, 0x62, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +//--------------------------------------------------------------------------- diff --git a/include/emubase.h b/include/emubase.h new file mode 100644 index 0000000..a0cc9fe --- /dev/null +++ b/include/emubase.h @@ -0,0 +1,17 @@ +#ifndef _EMUBASE_H_ +#define _EMUBASE_H_ + +char loadfilename[256]; +int frame; + +extern void emulation(); + +extern int load_address; +//--------------------------------------------------------------------------- +extern int start_pc; +extern int init_breakpoint; +extern int init_cycles_per_tick; +//--------------------------------------------------------------------------- +extern char emulation_run; + +#endif diff --git a/include/emuversion.h b/include/emuversion.h new file mode 100644 index 0000000..2eb03e4 --- /dev/null +++ b/include/emuversion.h @@ -0,0 +1,4 @@ +//--------------------------------------------------------------------------- + static char emuversion[]="BiGFooT's 65EL02 Emulator V0.12"; + static char eloraam[]="With Eloraam's permission, for enhanced compatibility the CPU emulation is based partly on RedPower"; +//--------------------------------------------------------------------------- diff --git a/include/memory/memory.h b/include/memory/memory.h new file mode 100644 index 0000000..ea0e941 --- /dev/null +++ b/include/memory/memory.h @@ -0,0 +1,19 @@ +unsigned char ram[0x10000]; +unsigned char rom_charset[0x800]; +unsigned char bootcode[0x100]; + +typedef struct { + unsigned short input; + unsigned short output; + unsigned short mask; + unsigned char irq; +} ioxstruct; + +ioxstruct ioextender[256]; + +int peripherals[256]; + +extern int memory_max; + +void mem_store(int ptr,unsigned char value); +unsigned char mem_load(int ptr); diff --git a/include/monitor.h b/include/monitor.h new file mode 100644 index 0000000..1140251 --- /dev/null +++ b/include/monitor.h @@ -0,0 +1,8 @@ +void moninit(); +int monitor(); + +void monitor_listing(char *file); +char *getlabelfromstr(char *label, char *line); +void cleanstring(char *str); +char *getlabel(int address); +int getaddress(char *label); \ No newline at end of file diff --git a/include/options.h b/include/options.h new file mode 100644 index 0000000..899ed61 --- /dev/null +++ b/include/options.h @@ -0,0 +1,22 @@ +#ifndef _OPTIONS_H_ +#define _OPTIONS_H_ + +void optinit(); +int help(); +int options(); +int optperipherals(); +void readoptions(); + +typedef struct { + int id; + char *name; + int len; + char *cfg_name; + + void (*ini_read)(char *str); + void (*print_handler)(int id, char *str); + int (*set_handler)(int id, int key, int keysym); + +} optionmenustruct; + +#endif diff --git a/include/screen.h b/include/screen.h new file mode 100644 index 0000000..8cd33ee --- /dev/null +++ b/include/screen.h @@ -0,0 +1,69 @@ +#ifndef _SCREEN_H_ +#define _SCREEN_H_ + +#define SCR_COLS 80 +#define SCR_ROWS 50 +#define SCR_SIZE (SCR_COLS*SCR_ROWS) + +#define SCR_ID_MONITOR 256 +#define SCR_ID_HELP 257 +#define SCR_ID_OPTIONS 258 +#define SCR_ID_PERIPHERALS 259 +#define SCR_ID_IOX 260 +#define SCR_ID_DRIVE 261 + +#define MAX_SCREENS 512 + +typedef struct { + int type; + int blink; + int attr; + + struct { + union { + unsigned char linear[SCR_SIZE]; + unsigned char rowcol[SCR_ROWS][SCR_COLS]; + }; + } chars; + + struct { + union { + unsigned short linear[SCR_SIZE]; + unsigned short rowcol[SCR_ROWS][SCR_COLS]; + }; + } attributes; + + union { + int col; + int cx; + }; + + union { + int row; + int cy; + + }; + +} screenstruct; + +screenstruct *screens[MAX_SCREENS]; +screenstruct screencache; + +unsigned int last_screen_type; + +void initscreen(); +void scrattrfill(int scr, unsigned short attr); +void scrclr(int scr); +screenstruct *openscreen(int scr); +void closescreen(int scr); +void shutdownscreen(); +void displayscreen(int scr); +void scrxy(int scr, int x, int y); +void scrattr(int scr, unsigned short attr); +void scrblink(int scr, unsigned char blink); +void scrtype(int scr, unsigned char type); +void scrprintf(int scr, const char *fmt, ...); +void scrwindow(int scr, int x, int y, int sx, int sy, unsigned short attr, char *hdr); +void scrclone(int scr, int src); + +#endif diff --git a/include/video/colors.h b/include/video/colors.h new file mode 100644 index 0000000..e403eb7 --- /dev/null +++ b/include/video/colors.h @@ -0,0 +1,25 @@ +//--------------------------------------------------------------------------- +static unsigned int colors[]={ + 0xff191d19, // 0x00 + 0xfffcf9fc, // 0x01 + 0xff933a4c, // 0x02 + 0xffb6fafa, // 0x03 + 0xffd27ded, // 0x04 + 0xff6acf6f, // 0x05 + 0xff4f44d8, // 0x06 + 0xfffbfb8b, // 0x07 + 0xffd89c5b, // 0x08 + 0xff7f5307, // 0x09 + 0xffef839f, // 0x0a + 0xff575753, // 0x0b + 0xffa3a7a7, // 0x0c + 0xffb7fbbf, // 0x0d + 0xffa397ff, // 0x0e +// 0xffeff9e7, // 0x0f + 0xffd8d8d8, // 0x0f + 0xff011d00, + 0xffff00ff, + 0xfffaafbe, + 0xff463e41, + 0xff000000}; +//--------------------------------------------------------------------------- diff --git a/include/video/gbuffer.h b/include/video/gbuffer.h new file mode 100644 index 0000000..03869ec --- /dev/null +++ b/include/video/gbuffer.h @@ -0,0 +1,19 @@ +#define C_SIZEX 125 +#define C_SIZEY 56 + +#define WINSIZEX (C_SIZEX*8)+4 +#define WINSIZEY (C_SIZEY*8)+4 +#define SIZEX WINSIZEX +#define SIZEY WINSIZEY + + +int lastkey; +int lastkeysym; +int lastkeymod; +int timer_tick; + +int startptc(); +void updateptc(); +void endptc(); +void events(); +void drawstring(int cx,int cy, unsigned char *tempstring, unsigned char fgcolor, unsigned char bgcolor, void *charset); diff --git a/roms/charset.rom b/roms/charset.rom new file mode 100644 index 0000000..be4fde3 Binary files /dev/null and b/roms/charset.rom differ diff --git a/roms/redforth.img b/roms/redforth.img new file mode 100644 index 0000000..12fa5cb Binary files /dev/null and b/roms/redforth.img differ diff --git a/roms/rpcboot.bin b/roms/rpcboot.bin new file mode 100644 index 0000000..60ce042 Binary files /dev/null and b/roms/rpcboot.bin differ diff --git a/roms/rpcboot.bin.mcfs b/roms/rpcboot.bin.mcfs new file mode 100644 index 0000000..60ce042 Binary files /dev/null and b/roms/rpcboot.bin.mcfs differ diff --git a/roms/rpcboot.bin.orig b/roms/rpcboot.bin.orig new file mode 100644 index 0000000..0a17857 Binary files /dev/null and b/roms/rpcboot.bin.orig differ diff --git a/roms/test_iox.img b/roms/test_iox.img new file mode 100644 index 0000000..42aef77 Binary files /dev/null and b/roms/test_iox.img differ diff --git a/src/SDLMain.m b/src/SDLMain.m new file mode 100644 index 0000000..2434f81 --- /dev/null +++ b/src/SDLMain.m @@ -0,0 +1,381 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#include "SDL.h" +#include "SDLMain.h" +#include /* for MAXPATHLEN */ +#include + +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ +@interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; +@end + +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + const NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ +@interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; +@end +#endif + +@interface NSApplication (SDLApplication) +@end + +@implementation NSApplication (SDLApplication) +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} +@end + +/* The main class of the application, the application's delegate */ +@implementation SDLMain + +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { + chdir(parentdir); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } +} + +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } +} + +#else + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [NSApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [NSApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif + + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} +@end + + +@implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + +@end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } + +#if SDL_USE_NIB_FILE + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; +} + diff --git a/src/calc.c b/src/calc.c new file mode 100644 index 0000000..73b33a9 --- /dev/null +++ b/src/calc.c @@ -0,0 +1,381 @@ +/* ------------------------------------------------------------------------- */ +#include +#include +#include +#include + +/* ------------------------------------------------------------------------- */ +double getbinary(char *str,int *ptr) +{ + double bin=0; + + while (*str=='0' || *str=='1') + { + bin = (bin*2) + (*str++ -'0'); + *ptr += 1; + } + + return (bin); +}; +/* ------------------------------------------------------------------------- */ + +double getdecimal(char *str,int *ptr) +{ + +double dec=0; +int i=0,end=0,neg=0,fraction=0; + + if (str[i]=='-') {neg=1;i++;}; + + do { + + if ((str[i] >='0') && (str[i] <='9')) + dec = (dec * 10) + (str[i] - '0'); + else if (str[i] == '.') fraction=i; + else end=1; + + i++; + } while(!end); + + if (neg) + dec *= -1; + if (fraction) + dec = dec/pow(10,(i-2-fraction)); + + + *ptr=*ptr+i-1; + + return (dec); + +}; + + + +/**************/ + +double gethexa(char *str,int *ptr){ + + double hex=0; + int end=0; + + while (*str && !end) + { + if ((*str >='0') && (*str <='9')) + hex = (hex * 16) + (*str - '0'); + else if ((*str >='a') && (*str <= 'f')) + hex = (hex * 16) + (*str - 'a' + 10); + else if ((*str >='A') && (*str <= 'F')) + hex = (hex * 16) + (*str - 'A' + 10); + else end = 1; + + if (!end) + { + str++; + *ptr += 1; + } + } + + return (hex); + +}; + +/*******************************************************************/ + +void veremcompress(char * verem,double * szamok,int begin,int * end){ + +/* + * Az adott tartomanyban a verembol kiszedi a felesleges zarojeleket, + * es az ures (' ') bejegyzeseket + * + */ + +int i,j,lyuk; +int zarojel,job; + +// kiszedem a lyukakat, aztan a zarjeleket, aztan megint lyuk, es igy tovabb... + + +do { +job=0; + +// lyukszedes: +do { +lyuk=0; +for (i=begin;i<=*end;i++) { + if (verem[i]==' ') { + lyuk=1; + for (j=i;j<*end;j++) {verem[j]=verem[j+1]; + szamok[j]=szamok[j+1];}; + verem[j]=' '; + (*end)--; + }; +}; +} while (lyuk); + +// a felesleges zarojeleket szedem ki: +zarojel=0; +for (i=begin;i<=*end;i++) {if (verem[i]=='(') {if (verem[i+1]==')') {verem[i]=' '; + verem[i+1]=' '; + job=1;} else + if (verem[i+1]=='1' && verem[i+2]==')') {verem[i]=' '; + verem[i+2]=' '; + job=1;} else + zarojel++; + }; + if (verem[i]==')') zarojel--; + }; +if (zarojel!=0) {printf("Zarojelezesi hiba!\n");exit(-1);}; +} while (job); + +//ellenorzom, hogy van-e ket szam egymas mogott, hogy nincs koztuk muveleti jel. +//ilyen nem lehet alapbol, tehat input string hiba + +for (i=begin;i<*end;i++) if (verem[i]=='1' && verem[i+1]=='1') {printf("Bemeneti stringben hiba!\n");exit(-1);}; + + +}; + +/*******************************************************************/ + +double getnumber(char *verem,double *szamok,int begin,int end){ + +int i,j,zarojel,job; + + +//Eloszoris az indulaskor is lehetseges felesleges szokozoket, es a felesleges zarojeleket szurom ki: +//Ha a zarojelezesben hiba van, az is kiderul itt! +veremcompress(verem,szamok,begin,&end); + +//Azutan eloszor a zarojelben levo dolgokat szamolom ki, hogy vegul egy () se maradjon. + +do { +job=0; +for (i=begin;i<=end;i++) {if ((verem[i]=='(') || (verem[i]==')')) job=1;}; +if (job) {for (i=begin;verem[i]!='(';i++); + j=i;zarojel=1; + do {j++; + if (verem[j]=='(') zarojel++; + if (verem[j]==')') zarojel--; + } while(zarojel!=0); + getnumber(verem,szamok,i+1,j-1); + verem[i]=' '; + verem[j]=' '; + veremcompress(verem,szamok,begin,&end); + }; +} while(job!=0); + + +// Mostmar garantaltan nincs zarojel, johet sorrendben a tovabbi szamolas: + + +while(begin!=end) { + +// Elso korben HATVANYozast keresek. + +for (i=begin;i<=end;i++) {if (verem[i]=='^') { + szamok[i]=pow(szamok[i-1],szamok[i+1]); + verem[i]='1'; + verem[i-1]=' '; + verem[i+1]=' '; + veremcompress(verem,szamok,begin,&end); + }; + }; + +// Masodik korben a SZORZASokkal es az OSZTASokkal vegzek + +for (i=begin;i<=end;i++) {if (verem[i]=='*') {szamok[i]=szamok[i-1]*szamok[i+1]; + verem[i]='1'; + verem[i-1]=' '; + verem[i+1]=' '; + veremcompress(verem,szamok,begin,&end); + }; + if (verem[i]=='/') {szamok[i]=szamok[i-1]/szamok[i+1]; + verem[i]='1'; + verem[i-1]=' '; + verem[i+1]=' '; + veremcompress(verem,szamok,begin,&end); + }; + }; + +// Harmadik korben az OSSZEADAS es a KIVONAS van mar csak + +for (i=begin;i<=end;i++) {if (verem[i]=='+') {szamok[i]=szamok[i-1]+szamok[i+1]; + verem[i]='1'; + verem[i-1]=' '; + verem[i+1]=' '; + veremcompress(verem,szamok,begin,&end); + }; + if (verem[i]=='-') {szamok[i]=szamok[i-1]-szamok[i+1]; + verem[i]='1'; + verem[i-1]=' '; + verem[i+1]=' '; + veremcompress(verem,szamok,begin,&end); + }; + }; +}; + +return(szamok[begin]); +}; + + +/*******************************************************************/ + + +const char* calc(char *kifejezes,double * result){ + +double *szamok; +char *verem; +int i,veremp,job,j; +char *expr; +char *err; + +char *ptr; + +// First I remove the spaces from the expression + + if (NULL==(expr=(char*)calloc(strlen(kifejezes),1))) + { + printf("Out of memory!\n"); + exit(-1); + }; + + ptr = expr; + while (*kifejezes) // strip spaces + { + if (*kifejezes != ' ') + *ptr++ = *kifejezes; + + kifejezes++; + } + + *ptr++ = 0; + + if ( NULL == (verem=(char*)malloc( strlen(expr)+1 )) ) + { + printf("Out of memory!\n"); + exit(-1); + }; + if ( NULL == (szamok=(double*)malloc( (strlen(expr)+1) * sizeof(double) )) ) + { + printf("Out of memory!\n"); + exit(-1); + }; + +/* + * Beolvasom a expr-bol a szamokat, es a muveleti jeleket. + * + * Veremtartalom a kifejezesben levo elemeket tartalmazza: + * + * (,),+,-,*,/,^ A szokasos muveleti jelek (es csak ezek!) + * 1 : ezen a helyen egy szam all, a szamok altal tartalmazott tombbol keresheto ki, melyik. + * + */ + + +//A legelso karakter nem lehet barmi, kulon vizsgalom: +i=veremp=0; +switch(expr[i]) { + case '(' : verem[veremp++]='(';i++;break; + case ')' : return ("zarojelezesi hiba"); + break; + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; + case '+' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[++i],&i); break; + case '-' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; + case '%' : verem[veremp]='1'; i++; szamok[veremp++]=getbinary(&expr[i],&i); break; + case '$' : verem[veremp]='1'; i++; szamok[veremp++]=gethexa(&expr[i],&i); break; + default : return ("hiba0"); + }; + +if (strlen(expr)!=i) +//most a tovabbi karakterek johetnek: +do { + if ((verem[veremp-1]=='1') || + (verem[veremp-1]==')')) { + switch(expr[i]) { + + case ')': + case '+': + case '-': + case '*': + case '/': + case '^': + verem[veremp++]=expr[i++]; + break; + default: + return ("hiba1"); + + }; + }; + if (verem[veremp-1]=='(') { + switch(expr[i]) { + case '(' : verem[veremp++]='(';i++;break; + case ')' : verem[veremp++]=')';i++;break; + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; + case '+' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[++i],&i); break; + case '-' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; + case '%' : verem[veremp]='1'; i++; szamok[veremp++]=getbinary(&expr[i],&i); break; + case '$' : verem[veremp]='1'; i++; szamok[veremp++]=gethexa(&expr[i],&i); break; + default : return ("hiba2"); + + }; + }; + if ((verem[veremp-1]=='^') || + (verem[veremp-1]=='*') || + (verem[veremp-1]=='/') || + (verem[veremp-1]=='+') || + (verem[veremp-1]=='-')) { + switch(expr[i]) { + case '(' : verem[veremp++]='(';i++;break; + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; + case '+' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[++i],&i); break; + case '-' : verem[veremp]='1'; szamok[veremp++]=getdecimal(&expr[i],&i); break; + case '%' : verem[veremp]='1'; i++; szamok[veremp++]=getbinary(&expr[i],&i); break; + case '$' : verem[veremp]='1'; i++; szamok[veremp++]=gethexa(&expr[i],&i); break; + default : return ("hiba3"); + }; + + }; + +} while (i +#include "cpu/65el02.h" +#include "memory/memory.h" + +int nospbug = 0; + +int readMem(int addr) +{ + int i = 0; + + while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x2ffff) != (cpu.regPC | 0x20000)) ) + i++; + + if (i <= cpu.breakpoint_count) // breakpoint hit + { + cpu.cycles = 0; + cpu.brk = 1; + + } + + return (mem_load(addr) & 0xff); + +} + +void writeMem(int addr, int val) +{ + int i = 0; + + while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x4ffff) != (cpu.regPC | 0x40000)) ) + i++; + + if (i <= cpu.breakpoint_count) // breakpoint hit + { + cpu.cycles = 0; + cpu.brk = 1; + + } + + mem_store(addr, val); +} + + +void +coldBootCPU() +{ + cpu.addrPOR = 0x2000; + cpu.addrBRK = 0x2000; + if (nospbug) + cpu.regSP = 0x1ff; + else + cpu.regSP = 0x200; + + cpu.regPC = 0x400; + cpu.regR = 0x300; + + cpu.regA = 0; + cpu.regX = 0; + cpu.regY = 0; + cpu.regD = 0; + cpu.flagC = 0; + cpu.flagZ = 0; + cpu.flagID = 0; + cpu.flagD = 0; + cpu.flagBRK = 0; + cpu.flagO = 0; + cpu.flagN = 0; + + cpu.flagE = 1; + cpu.flagM = 1; + cpu.flagX = 1; + + if (!cpu.byte0) + cpu.byte0 = 2; + if (!cpu.byte1) + cpu.byte1 = 1; + + cpu.cycles = 0; + cpu.ticks = 0; + cpu.brk = 0; + + if (!cpu.cycles_per_tick) + cpu.cycles_per_tick = 1000; +} + +void incPC() +{ + cpu.regPC = (cpu.regPC + 1) & 0xffff; +} + +int maskM() +{ + return cpu.flagM ? 0xff : 0xffff; +} + +int maskX() +{ + return cpu.flagX ? 0xff : 0xffff; +} + +int negM() +{ + return cpu.flagM ? 0x80 : 0x8000; +} + +int negX() +{ + return cpu.flagX ? 0x80 : 0x8000; +} + +int readB() +{ + int i = readMem(cpu.regPC); + incPC(); + return i; +} + +int readM_PC() +{ + int i = readMem(cpu.regPC); + incPC(); + if (!cpu.flagM) + { + i |= readMem(cpu.regPC) << 8; + incPC(); + } + return i; +} + +int readX_PC() +{ + int i = readMem(cpu.regPC); + incPC(); + if (!cpu.flagX) + { + i |= readMem(cpu.regPC) << 8; + incPC(); + } + return i; +} + +int readM(int addr) +{ + int i = readMem(addr); + if (!cpu.flagM) + i |= readMem(addr + 1) << 8; + return i; +} + +int readX(int addr) +{ + int i = readMem(addr); + if (!cpu.flagX) + i |= readMem(addr + 1) << 8; + return i; +} + +void writeM(int addr, int reg) +{ + writeMem(addr, reg); + if (!cpu.flagM) + writeMem(addr + 1, reg >> 8); +} + +void writeX(int addr, int reg) +{ + writeMem(addr, reg); + if (!cpu.flagX) + writeMem(addr + 1, reg >> 8); +} + +int readBX() +{ + int i = readMem(cpu.regPC) + cpu.regX; + if (cpu.flagX) + i &= 0xff; + incPC(); + return i; +} + +int readBY() +{ + int i = readMem(cpu.regPC) + cpu.regY; + if (cpu.flagX) + i &= 0xff; + incPC(); + return i; +} + +int readBS() +{ + int i = readMem(cpu.regPC) + cpu.regSP & 0xffff; + incPC(); + return i; +} + +int readBR() +{ + int i = readMem(cpu.regPC) + cpu.regR & 0xffff; + incPC(); + return i; +} + +int readBSWY() +{ + int i = readMem(cpu.regPC) + cpu.regSP & 0xffff; + incPC(); + return readW(i) + cpu.regY & 0xffff; +} + +int readBRWY() +{ + int i = readMem(cpu.regPC) + cpu.regR & 0xffff; + incPC(); + return readW(i) + cpu.regY & 0xffff; +} + +int readW_PC() +{ + int i = readMem(cpu.regPC); + incPC(); + i |= readMem(cpu.regPC) << 8; + incPC(); + return i; +} + +int readW(int addr) +{ + int i = readMem(addr); + i |= readMem(addr + 1) << 8; + return i; +} + +int readWX() +{ + int i = readMem(cpu.regPC); + incPC(); + i |= readMem(cpu.regPC) << 8; + incPC(); + return i + cpu.regX & 0xffff; +} + +int readWY() +{ + int i = readMem(cpu.regPC); + incPC(); + i |= readMem(cpu.regPC) << 8; + incPC(); + return i + cpu.regY & 0xffff; +} + +int readWXW() +{ + int i = readMem(cpu.regPC); + incPC(); + i |= readMem(cpu.regPC) << 8; + incPC(); + i = i + cpu.regX & 0xffff; + int j = readMem(i); + j |= readMem(i + 1) << 8; + return j; +} + +int readBW() +{ + int i = readMem(cpu.regPC); + incPC(); + int j = readMem(i); + j |= readMem(i + 1) << 8; + return j; +} + +int readWW() +{ + int i = readMem(cpu.regPC); + incPC(); + i |= readMem(cpu.regPC) << 8; + incPC(); + int j = readMem(i); + j |= readMem(i + 1) << 8; + return j; +} + +int readBXW() +{ + int i = readMem(cpu.regPC) + cpu.regX & 0xff; + incPC(); + int j = readMem(i); + j |= readMem(i + 1) << 8; + return j; +} + +int readBWY() +{ + int i = readMem(cpu.regPC); + incPC(); + int j = readMem(i); + j |= readMem(i + 1) << 8; + return j + cpu.regY & 0xffff; +} + +void upNZ_A() +{ + cpu.flagN = ((cpu.regA & negM()) > 0); + cpu.flagZ = (cpu.regA == 0); +} + +void upNZ(int i) +{ + cpu.flagN = ((i & negM()) > 0); + cpu.flagZ = (i == 0); +} + +void upNZX(int i) +{ + cpu.flagN = ((i & negX()) > 0); + cpu.flagZ = (i == 0); +} + +void push1(int b) +{ + if (nospbug) + writeMem(cpu.regSP, b); + + if (!cpu.flagE) + cpu.regSP = (cpu.regSP - 1) & 0xffff; + else + cpu.regSP = ((cpu.regSP - 1) & 0xff) | (cpu.regSP & 0xff00); + + if (!nospbug) + writeMem(cpu.regSP, b); +} + +void push1r(int b) +{ + cpu.regR = (cpu.regR - 1) & 0xffff; + writeMem(cpu.regR, b); +} + +void push2(int w) +{ + push1(w >> 8); + push1(w & 0xff); +} + +void push2r(int w) +{ + push1r(w >> 8); + push1r(w & 0xff); +} + +void pushM(int b) +{ + if (cpu.flagM) + push1(b); + else + push2(b); +} + +void pushX(int b) +{ + if (cpu.flagX) + push1(b); + else + push2(b); +} + +void pushMr(int b) +{ + if (cpu.flagM) + push1r(b); + else + push2r(b); +} + +void pushXr(int b) +{ + if (cpu.flagX) + push1r(b); + else + push2r(b); +} + +int pop1() +{ + int tr; + + if (!nospbug) + tr = readMem(cpu.regSP); + + if (!cpu.flagE) + cpu.regSP = (cpu.regSP + 1) & 0xffff; + else + cpu.regSP = ((cpu.regSP + 1) & 0xff) | (cpu.regSP & 0xff00); + + if (nospbug) + tr = readMem(cpu.regSP); + + return tr; +} + +int pop1r() +{ + int tr = readMem(cpu.regR); + cpu.regR = (cpu.regR + 1) & 0xffff; + return tr; +} + +int pop2() +{ + int tr = pop1(); + tr |= pop1() << 8; + return tr; +} + +int pop2r() +{ + int tr = pop1r(); + tr |= pop1r() << 8; + return tr; +} + +int popM() +{ + if (cpu.flagM) + return pop1(); + return pop2(); +} + +int popMr() +{ + if (cpu.flagM) + return pop1r(); + return pop2r(); +} + +int popX() +{ + if (cpu.flagX) + return pop1(); + return pop2(); +} + +int popXr() +{ + if (cpu.flagX) + return pop1r(); + return pop2r(); +} + +int getFlags() +{ + return (cpu.flagC ? 1 : 0) | (cpu.flagZ ? 2 : 0) | (cpu.flagID ? 4 : 0) | (cpu.flagD ? 8 : 0) | (cpu.flagX ? 16 : 0) | (cpu.flagM ? 32 : 0) | (cpu.flagO ? 64 : 0) | (cpu.flagN ? 128 : 0); +} + +void setFlags(int flags) +{ + int m2 = (flags & 0x20) > 0; + + cpu.flagC = ((flags & 0x1) > 0); + cpu.flagZ = ((flags & 0x2) > 0); + cpu.flagID = ((flags & 0x4) > 0); + cpu.flagD = ((flags & 0x8) > 0); + cpu.flagX = ((flags & 0x10) > 0); + cpu.flagO = ((flags & 0x40) > 0); + cpu.flagN = ((flags & 0x80) > 0); + + if (cpu.flagE) + { + cpu.flagX = 0; + cpu.flagM = 0; + } + else + { + cpu.flagX = ((flags & 0x10) > 0); + if (cpu.flagX) + { + cpu.regX &= 0xff; + cpu.regY &= 0xff; + } + + if (m2 != cpu.flagM) + { + if (m2) + { + cpu.regB = (cpu.regA >> 8); + cpu.regA &= 0xff; + } + else + { + cpu.regA |= cpu.regB << 8; + } + cpu.flagM = m2; + } + } + +} + +void i_adc(int val) +{ + if (cpu.flagM) + { + if (cpu.flagD) + { + int v1 = (cpu.regA & 0x0f) + (val & 0x0f) + (cpu.flagC ? 1 : 0); + if (v1 > 9) + v1 = (v1 + 6 & 0x0f) + 16; + int v2 = (cpu.regA & 0xf0) + (val & 0xf0) + v1; + if (v2 > 160) + v2 += 96; + cpu.flagC = (v2 > 100); + cpu.regA = (v2 & 0xff); + cpu.flagO = 0; + } + else + { + int v = cpu.regA + val + (cpu.flagC ? 1 : 0); + cpu.flagC = (v > 0xff); + cpu.flagO = (((v ^ cpu.regA) & (v ^ val) & 0x80) > 0); + + cpu.regA = (v & 0xff); + } + } + else + { + int v = cpu.regA + val + (cpu.flagC ? 1 : 0); + cpu.flagC = (v > 0xffff); + cpu.flagO = (((v ^ cpu.regA) & (v ^ val) & 0x8000) > 0); + + cpu.regA = (v & 0xffff); + } + upNZ_A(); +} + +void i_sbc(int val) +{ + if (cpu.flagM) + { + if (cpu.flagD) + { + int v1 = (cpu.regA & 0x0f) - (val & 0x0f) + (cpu.flagC ? 1 : 0) - 1; + if (v1 < 0) + v1 = (v1 - 6 & 0x0f) - 16; + int v2 = (cpu.regA & 0xf0) - (val & 0xf0) + v1; + if (v2 < 0) + v2 -= 96; + cpu.flagC = (v2 < 100); + cpu.regA = (v2 & 0xff); + cpu.flagO = 0; + } + else + { + int v = cpu.regA - val + (cpu.flagC ? 1 : 0) - 1; + + cpu.flagC = ((v & 0x100) == 0); + + cpu.flagO = (((v ^ cpu.regA) & (v ^ -val) & 0x80) > 0); + cpu.regA = (v & 0xff); + } + } + else + { + int v = cpu.regA - val + (cpu.flagC ? 1 : 0) - 1; + + cpu.flagC = ((v & 0x10000) == 0); + + cpu.flagO = (((v ^ cpu.regA) & (v ^ -val) & 0x8000) > 0); + cpu.regA = (v & 0xffff); + } + upNZ_A(); +} + +void i_mul(int val) +{ + int v; + + if (cpu.flagM) + { + + if (cpu.flagC) + v = (signed char) val * (signed char) cpu.regA; + else + v = (unsigned char) val * (unsigned char) cpu.regA; + + cpu.regA = (v & 0xff); + cpu.regD = (v >> 8 & 0xff); + cpu.flagN = (v < 0); + cpu.flagZ = (v == 0); + cpu.flagO = ((cpu.regD != 0) && (cpu.regD != 0xff)); + } + else + { + if (cpu.flagC) + v = (short) val * (short) cpu.regA; + else + v = (unsigned short) val * (unsigned short) cpu.regA; + + cpu.regA = (v & 0xffff); + cpu.regD = ((v >> 16) & 0xffff); + cpu.flagN = (v < 0); + cpu.flagZ = (v == 0); + cpu.flagO = ((cpu.regD != 0) && (cpu.regD != 0xffff)); + } + +} + +void i_div(int val) +{ + int q; + + if (val == 0) + { + cpu.regA = 0; + cpu.regD = 0; + cpu.flagO = 1; + cpu.flagZ = 0; + cpu.flagN = 0; + return; + } + if (cpu.flagM) + { + if (cpu.flagC) + { + q = (signed char) cpu.regD << 8 | cpu.regA; + val = (signed char) val; + } + else + q = (unsigned char) cpu.regD << 8 | cpu.regA; + + cpu.regD = (q % val & 0xff); + q /= val; + cpu.regA = (q & 0xff); + if (cpu.flagC) + cpu.flagO = ((q > 127) || (q < -128)); + else + cpu.flagO = (q > 255); + + cpu.flagZ = (cpu.regA == 0); + cpu.flagN = (q < 0); + } + else + { + if (cpu.flagC) + { + q = (short) cpu.regD << 16 | cpu.regA; + val = (short) val; + } + else + q = (unsigned short) cpu.regD << 16 | cpu.regA; + + cpu.regD = (q % val & 0xffff); + q /= val; + cpu.regA = (q & 0xffff); + if (cpu.flagC) + cpu.flagO = ((q > 32767) || (q < -32768)); + else + cpu.flagO = (q > 65535); + + cpu.flagZ = (cpu.regA == 0); + cpu.flagN = (q < 0); + } +} + +void i_and(int val) +{ + cpu.regA &= val; + upNZ_A(); +} + +void i_asl(int addr) +{ + int i = readM(addr); + + cpu.flagC = ((i & negM()) > 0); + i = i << 1 & maskM(); + upNZ(i); + writeM(addr, i); +} + +void i_lsr(int addr) +{ + int i = readM(addr); + cpu.flagC = ((i & 0x1) > 0); + i = i >> 1; + upNZ(i); + writeM(addr, i); +} + +void i_rol(int addr) +{ + int i = readM(addr); + int n = (i << 1 | (cpu.flagC ? 1 : 0)) & maskM(); + cpu.flagC = ((i & negM()) > 0); + upNZ(n); + writeM(addr, n); +} + +void i_ror(int addr) +{ + int i = readM(addr); + int n = i >> 1 | (cpu.flagC ? negM() : 0); + cpu.flagC = ((i & 0x1) > 0); + upNZ(n); + writeM(addr, n); +} + +void i_brc(int cond) +{ + int n = readB(); + if (cond) + cpu.regPC = (cpu.regPC + (signed char) n & 0xffff); +} + +void i_bit(int val) +{ + if (cpu.flagM) + { + cpu.flagO = ((val & 0x40) > 0); + cpu.flagN = ((val & 0x80) > 0); + } + else + { + cpu.flagO = ((val & 0x4000) > 0); + cpu.flagN = ((val & 0x8000) > 0); + } + cpu.flagZ = ((val & cpu.regA) > 0); +} + +void i_trb(int val) +{ + cpu.flagZ = ((val & cpu.regA) > 0); + cpu.regA &= (val ^ 0xffffffff); +} + +void i_tsb(int val) +{ + cpu.flagZ = ((val & cpu.regA) > 0); + cpu.regA |= val; +} + +void i_cmp(int reg, int val) +{ + reg -= val; + cpu.flagC = (reg >= 0); + cpu.flagZ = (reg == 0); + cpu.flagN = ((reg & negM()) > 0); +} + +void i_cmpx(int reg, int val) +{ + reg -= val; + cpu.flagC = (reg >= 0); + cpu.flagZ = (reg == 0); + cpu.flagN = ((reg & negX()) > 0); +} + +void i_dec(int addr) +{ + int i = readM(addr); + i = i - 1 & maskM(); + writeM(addr, i); + upNZ(i); +} + +void i_inc(int addr) +{ + int i = readM(addr); + i = i + 1 & maskM(); + writeM(addr, i); + upNZ(i); +} + +void i_eor(int val) +{ + cpu.regA ^= val; + upNZ_A(); +} + +void i_or(int val) +{ + cpu.regA |= val; + upNZ_A(); +} + +void i_mmu(int mmu) +{ + int t; + + switch (mmu) + { + case 0x00: + t = cpu.regA & 0xff; + + if ((t != cpu.mmuRBA) && (!cpu.no_io_penality)) + cpu.rbTimeout = 1; + + cpu.mmuRBA = t; + break; + case 0x80: + cpu.regA = cpu.mmuRBA; + break; + case 0x01: + cpu.mmuRBB = cpu.regA; + break; + case 0x81: + cpu.regA = cpu.mmuRBB; + if (!cpu.flagM) + break; + cpu.regB = (cpu.regA >> 8); + cpu.regA &= 0xff; + break; + case 0x02: + cpu.mmuEnRB = 1; + break; + case 0x82: + cpu.mmuEnRB = 0; + break; + case 0x03: + cpu.mmuRBW = cpu.regA; + break; + case 0x83: + cpu.regA = cpu.mmuRBW; + if (!cpu.flagM) + break; + cpu.regB = (cpu.regA >> 8); + cpu.regA &= 0xff; + break; + case 0x04: + cpu.mmuEnRBW = 1; + break; + case 0x84: + cpu.mmuEnRBW = 0; + break; + case 0x05: + cpu.addrBRK = cpu.regA; + break; + case 0x85: + cpu.regA = cpu.addrBRK; + if (!cpu.flagM) + break; + cpu.regB = (cpu.regA >> 8); + cpu.regA &= 0xff; + break; + case 0x06: + cpu.addrPOR = cpu.regA; + break; + case 0x86: + cpu.regA = cpu.addrPOR; + if (!cpu.flagM) + break; + cpu.regB = (cpu.regA >> 8); + cpu.regA &= 0xff; + break; + default: + printf("invalid MMU parameter %02x\n",mmu); + } +} + +void executeInsn() +{ + int insn = readMem(cpu.regPC); + + incPC(); + int n; + switch (insn) + { + case 0x69: + i_adc(readM_PC()); + break; + case 0x65: + i_adc(readM(readB())); + break; + case 0x75: + i_adc(readM(readBX())); + break; + case 0x6d: + i_adc(readM(readW_PC())); + break; + case 0x7d: + i_adc(readM(readWX())); + break; + case 0x79: + i_adc(readM(readWY())); + break; + case 0x61: + i_adc(readM(readBXW())); + break; + case 0x71: + i_adc(readM(readBWY())); + break; + case 0x72: + i_adc(readM(readBW())); + break; + case 0x63: + i_adc(readM(readBS())); + break; + case 0x73: + i_adc(readM(readBSWY())); + break; + case 0x67: + i_adc(readM(readBR())); + break; + case 0x77: + i_adc(readM(readBRWY())); + break; + case 0x29: + i_and(readM_PC()); + break; + case 0x25: + i_and(readM(readB())); + break; + case 0x35: + i_and(readM(readBX())); + break; + case 0x2d: + i_and(readM(readW_PC())); + break; + case 0x3d: + i_and(readM(readWX())); + break; + case 0x39: + i_and(readM(readWY())); + break; + case 0x21: + i_and(readM(readBXW())); + break; + case 0x31: + i_and(readM(readBWY())); + break; + case 0x32: + i_and(readM(readBW())); + break; + case 0x23: + i_and(readM(readBS())); + break; + case 0x33: + i_and(readM(readBSWY())); + break; + case 0x27: + i_and(readM(readBR())); + break; + case 0x37: + i_and(readM(readBRWY())); + break; + case 0x0a: + cpu.flagC = ((cpu.regA & negM()) > 0); + cpu.regA = (cpu.regA << 1 & maskM()); + upNZ_A(); + break; + case 0x06: + i_asl(readB()); + break; + case 0x16: + i_asl(readBX()); + break; + case 0x0e: + i_asl(readW_PC()); + break; + case 0x1e: + i_asl(readWX()); + break; + case 0x90: + i_brc(!cpu.flagC); + break; + case 0xb0: + i_brc(cpu.flagC); + break; + case 0xf0: + i_brc(cpu.flagZ); + break; + case 0x30: + i_brc(cpu.flagN); + break; + case 0xd0: + i_brc(!cpu.flagZ); + break; + case 0x10: + i_brc(!cpu.flagN); + break; + case 0x50: + i_brc(!cpu.flagO); + break; + case 0x70: + i_brc(cpu.flagO); + break; + case 0x80: + i_brc(1); + break; + case 0x89: + cpu.flagZ = ((readM_PC() & cpu.regA) == 0); + break; + case 0x24: + i_bit(readM(readB())); + break; + case 0x34: + i_bit(readM(readBX())); + break; + case 0x2c: + i_bit(readM(readW_PC())); + break; + case 0x3c: + i_bit(readM(readWX())); + break; + case 0x00: + push2(cpu.regPC); + push1(getFlags()); + cpu.flagBRK = 1; + cpu.regPC = cpu.addrBRK; + break; + case 0x18: + cpu.flagC = 0; + break; + case 0xd8: + cpu.flagD = 0; + break; + case 0x58: + cpu.flagID = 0; + break; + case 0xb8: + cpu.flagO = 0; + break; + case 0xc9: + i_cmp(cpu.regA, readM_PC()); + break; + case 0xc5: + i_cmp(cpu.regA, readM(readB())); + break; + case 0xd5: + i_cmp(cpu.regA, readM(readBX())); + break; + case 0xcd: + i_cmp(cpu.regA, readM(readW_PC())); + break; + case 0xdd: + i_cmp(cpu.regA, readM(readWX())); + break; + case 0xd9: + i_cmp(cpu.regA, readM(readWY())); + break; + case 0xc1: + i_cmp(cpu.regA, readM(readBXW())); + break; + case 0xd1: + i_cmp(cpu.regA, readM(readBWY())); + break; + case 0xd2: + i_cmp(cpu.regA, readM(readBW())); + break; + case 0xc3: + i_cmp(cpu.regA, readM(readBS())); + break; + case 0xd3: + i_cmp(cpu.regA, readM(readBSWY())); + break; + case 0xc7: + i_cmp(cpu.regA, readM(readBR())); + break; + case 0xd7: + i_cmp(cpu.regA, readM(readBRWY())); + break; + case 0xe0: + i_cmpx(cpu.regX, readX_PC()); + break; + case 0xe4: + i_cmpx(cpu.regX, readX(readB())); + break; + case 0xec: + i_cmpx(cpu.regX, readX(readW_PC())); + break; + case 0xc0: + i_cmpx(cpu.regY, readX_PC()); + break; + case 0xc4: + i_cmpx(cpu.regY, readX(readB())); + break; + case 0xcc: + i_cmpx(cpu.regY, readX(readW_PC())); + break; + case 0x3a: + cpu.regA = (cpu.regA - 1 & maskM()); + upNZ(cpu.regA); + break; + case 0xc6: + i_dec(readB()); + break; + case 0xd6: + i_dec(readBX()); + break; + case 0xce: + i_dec(readW_PC()); + break; + case 0xde: + i_dec(readWX()); + break; + case 0xca: + cpu.regX = (cpu.regX - 1 & maskX()); + upNZ(cpu.regX); + break; + case 0x88: + cpu.regY = (cpu.regY - 1 & maskX()); + upNZ(cpu.regY); + break; + case 0x49: + i_eor(readM_PC()); + break; + case 0x45: + i_eor(readM(readB())); + break; + case 0x55: + i_eor(readM(readBX())); + break; + case 0x4d: + i_eor(readM(readW_PC())); + break; + case 0x5d: + i_eor(readM(readWX())); + break; + case 0x59: + i_eor(readM(readWY())); + break; + case 0x41: + i_eor(readM(readBXW())); + break; + case 0x51: + i_eor(readM(readBWY())); + break; + case 0x52: + i_eor(readM(readBW())); + break; + case 0x43: + i_eor(readM(readBS())); + break; + case 0x53: + i_eor(readM(readBSWY())); + break; + case 0x47: + i_eor(readM(readBR())); + break; + case 0x57: + i_eor(readM(readBRWY())); + break; + case 0x1a: + cpu.regA = (cpu.regA + 1 & maskM()); + upNZ(cpu.regA); + break; + case 0xe6: + i_inc(readB()); + break; + case 0xf6: + i_inc(readBX()); + break; + case 0xee: + i_inc(readW_PC()); + break; + case 0xfe: + i_inc(readWX()); + break; + case 0xe8: + cpu.regX = (cpu.regX + 1 & maskX()); + upNZ(cpu.regX); + break; + case 0xc8: + cpu.regY = (cpu.regY + 1 & maskX()); + upNZ(cpu.regY); + break; + case 0x4c: + cpu.regPC = readW_PC(); + break; + case 0x6c: + cpu.regPC = readWW(); + break; + case 0x7c: + cpu.regPC = readWXW(); + break; + case 0x20: + push2(cpu.regPC + 1); + cpu.regPC = readW_PC(); + break; + case 0xfc: + push2(cpu.regPC + 1); + cpu.regPC = readWXW(); + break; + case 0xa9: + cpu.regA = readM_PC(); + upNZ_A(); + break; + case 0xa5: + cpu.regA = readM(readB()); + upNZ_A(); + break; + case 0xb5: + cpu.regA = readM(readBX()); + upNZ_A(); + break; + case 0xad: + cpu.regA = readM(readW_PC()); + upNZ_A(); + break; + case 0xbd: + cpu.regA = readM(readWX()); + upNZ_A(); + break; + case 0xb9: + cpu.regA = readM(readWY()); + upNZ_A(); + break; + case 0xa1: + cpu.regA = readM(readBXW()); + upNZ_A(); + break; + case 0xb1: + cpu.regA = readM(readBWY()); + upNZ_A(); + break; + case 0xb2: + cpu.regA = readM(readBW()); + upNZ_A(); + break; + case 0xa3: + cpu.regA = readM(readBS()); + upNZ_A(); + break; + case 0xb3: + cpu.regA = readM(readBSWY()); + upNZ_A(); + break; + case 0xa7: + cpu.regA = readM(readBR()); + upNZ_A(); + break; + case 0xb7: + cpu.regA = readM(readBRWY()); + upNZ_A(); + break; + case 0xa2: + cpu.regX = readX_PC(); + upNZ(cpu.regX); + break; + case 0xa6: + cpu.regX = readX(readB()); + upNZ(cpu.regX); + break; + case 0xb6: + cpu.regX = readX(readBY()); + upNZ(cpu.regX); + break; + case 0xae: + cpu.regX = readX(readW_PC()); + upNZ(cpu.regX); + break; + case 0xbe: + cpu.regX = readX(readWY()); + upNZ(cpu.regX); + break; + case 0xa0: + cpu.regY = readX_PC(); + upNZ(cpu.regY); + break; + case 0xa4: + cpu.regY = readX(readB()); + upNZ(cpu.regY); + break; + case 0xb4: + cpu.regY = readX(readBX()); + upNZ(cpu.regY); + break; + case 0xac: + cpu.regY = readX(readW_PC()); + upNZ(cpu.regY); + break; + case 0xbc: + cpu.regY = readX(readWX()); + upNZ(cpu.regY); + break; + case 0x4a: + cpu.flagC = ((cpu.regA & 0x1) > 0); + cpu.regA = cpu.regA >> 1; + upNZ_A(); + break; + case 0x46: + i_lsr(readB()); + break; + case 0x56: + i_lsr(readBX()); + break; + case 0x4e: + i_lsr(readW_PC()); + break; + case 0x5e: + i_lsr(readWX()); + break; + case 0xea: + break; + case 0x09: + i_or(readM_PC()); + break; + case 0x05: + i_or(readM(readB())); + break; + case 0x15: + i_or(readM(readBX())); + break; + case 0x0d: + i_or(readM(readW_PC())); + break; + case 0x1d: + i_or(readM(readWX())); + break; + case 0x19: + i_or(readM(readWY())); + break; + case 0x01: + i_or(readM(readBXW())); + break; + case 0x11: + i_or(readM(readBWY())); + break; + case 0x12: + i_or(readM(readBW())); + break; + case 0x03: + i_or(readM(readBS())); + break; + case 0x13: + i_or(readM(readBSWY())); + break; + case 0x07: + i_or(readM(readBR())); + break; + case 0x17: + i_or(readM(readBRWY())); + break; + case 0x48: + pushM(cpu.regA); + break; + case 0x08: + push1(getFlags()); + break; + case 0xda: + pushX(cpu.regX); + break; + case 0x5a: + pushX(cpu.regY); + break; + case 0x68: + cpu.regA = popM(); + upNZ_A(); + break; + case 0x28: + setFlags(pop1()); + break; + case 0xfa: + cpu.regX = popX(); + upNZX(cpu.regX); + break; + case 0x7a: + cpu.regY = popX(); + upNZX(cpu.regY); + break; + case 0x2a: + n = (cpu.regA << 1 | (cpu.flagC ? 1 : 0)) & maskM(); + cpu.flagC = ((cpu.regA & negM()) > 0); + cpu.regA = n; + upNZ_A(); + break; + case 0x26: + i_rol(readB()); + break; + case 0x36: + i_rol(readBX()); + break; + case 0x2e: + i_rol(readW_PC()); + break; + case 0x3e: + i_rol(readWX()); + break; + case 0x6a: + n = cpu.regA >> 1 | (cpu.flagC ? negM() : 0); + cpu.flagC = ((cpu.regA & 0x1) > 0); + cpu.regA = n; + upNZ_A(); + break; + case 0x66: + i_ror(readB()); + break; + case 0x76: + i_ror(readBX()); + break; + case 0x6e: + i_ror(readW_PC()); + break; + case 0x7e: + i_ror(readWX()); + break; + case 0x40: + setFlags(pop1()); + cpu.regPC = pop2(); + break; + case 0x60: + cpu.regPC = (pop2() + 1); + break; + case 0xe9: + i_sbc(readM_PC()); + break; + case 0xe5: + i_sbc(readM(readB())); + break; + case 0xf5: + i_sbc(readM(readBX())); + break; + case 0xed: + i_sbc(readM(readW_PC())); + break; + case 0xfd: + i_sbc(readM(readWX())); + break; + case 0xf9: + i_sbc(readM(readWY())); + break; + case 0xe1: + i_sbc(readM(readBXW())); + break; + case 0xf1: + i_sbc(readM(readBWY())); + break; + case 0xf2: + i_sbc(readM(readBW())); + break; + case 0xe3: + i_sbc(readM(readBS())); + break; + case 0xf3: + i_sbc(readM(readBSWY())); + break; + case 0xe7: + i_sbc(readM(readBR())); + break; + case 0xf7: + i_sbc(readM(readBRWY())); + break; + case 0x38: + cpu.flagC = 1; + break; + case 0xf8: + cpu.flagD = 1; + break; + case 0x78: + cpu.flagID = 1; + break; + case 0x85: + writeM(readB(), cpu.regA); + break; + case 0x95: + writeM(readBX(), cpu.regA); + break; + case 0x8d: + writeM(readW_PC(), cpu.regA); + break; + case 0x9d: + writeM(readWX(), cpu.regA); + break; + case 0x99: + writeM(readWY(), cpu.regA); + break; + case 0x81: + writeM(readBXW(), cpu.regA); + break; + case 0x91: + writeM(readBWY(), cpu.regA); + break; + case 0x92: + writeM(readBW(), cpu.regA); + break; + case 0x83: + writeM(readBS(), cpu.regA); + break; + case 0x93: + writeM(readBSWY(), cpu.regA); + break; + case 0x87: + writeM(readBR(), cpu.regA); + break; + case 0x97: + writeM(readBRWY(), cpu.regA); + break; + case 0x86: + writeX(readB(), cpu.regX); + break; + case 0x96: + writeX(readBY(), cpu.regX); + break; + case 0x8e: + writeX(readW_PC(), cpu.regX); + break; + case 0x84: + writeX(readB(), cpu.regY); + break; + case 0x94: + writeX(readBX(), cpu.regY); + break; + case 0x8c: + writeX(readW_PC(), cpu.regY); + break; + case 0xaa: + cpu.regX = cpu.regA; + if (cpu.flagX) + cpu.regX &= 0xff; + upNZX(cpu.regX); + break; + case 0xa8: + cpu.regY = cpu.regA; + if (cpu.flagX) + cpu.regY &= 0xff; + upNZX(cpu.regY); + break; + case 0xba: + cpu.regX = cpu.regSP; + if (cpu.flagX) + cpu.regX &= 0xff; + upNZX(cpu.regX); + break; + case 0x8a: + cpu.regA = cpu.regX; + if (cpu.flagM) + cpu.regA &= 0xff; + upNZ_A(); + break; + case 0x9a: + if (cpu.flagX) + cpu.regSP = (cpu.regSP & 0xff00 | cpu.regX & 0xff); + else + cpu.regSP = cpu.regX; + upNZX(cpu.regX); + break; + case 0x98: + cpu.regA = cpu.regY; + if (cpu.flagM) + cpu.regA &= 0xff; + upNZX(cpu.regY); + break; + case 0x64: + writeM(readB(), 0); + break; + case 0x74: + writeM(readBX(), 0); + break; + case 0x9c: + writeM(readW_PC(), 0); + break; + case 0x9e: + writeM(readWX(), 0); + break; + case 0x14: + i_trb(readM(readB())); + break; + case 0x1c: + i_trb(readM(readW_PC())); + break; + case 0x04: + i_tsb(readM(readB())); + break; + case 0x0c: + i_tsb(readM(readW_PC())); + break; + case 0xdb: + cpu.regPC--; + break; + case 0xcb: + cpu.waiTimeout = 1; + break; + case 0x9b: + cpu.regY = cpu.regX; + upNZX(cpu.regY); + break; + case 0xbb: + cpu.regX = cpu.regY; + upNZX(cpu.regX); + break; + case 0xf4: + push2(readW_PC()); + break; + case 0xd4: + push2(readBW()); + break; + case 0x62: + n = readB(); + push2(cpu.regPC + n); + break; + case 0xeb: + if (cpu.flagM) + { + n = cpu.regA; + cpu.regA = cpu.regB; + cpu.regB = n; + } + else + { + cpu.regA = (cpu.regA >> 8 & 0xff | cpu.regA << 8 & 0xff00); + } + break; + case 0xfb: + if (cpu.flagE == cpu.flagC) + break; + if (cpu.flagE) + { + cpu.flagE = 0; + cpu.flagC = 1; + } + else + { + cpu.flagE = 1; + cpu.flagC = 0; + if (!cpu.flagM) + cpu.regB = (cpu.regA >> 8); + cpu.flagM = 1; + cpu.flagX = 1; + cpu.regA &= 0xff; + cpu.regX &= 0xff; + cpu.regY &= 0xff; + } + break; + case 0xc2: + setFlags(getFlags() & (readB() ^ 0xffffffff)); + break; + case 0xe2: + setFlags(getFlags() | readB()); + break; + case 0x8b: + if (cpu.flagX) + cpu.regSP = (cpu.regR & 0xff00 | cpu.regX & 0xff); + else + cpu.regR = cpu.regX; + upNZX(cpu.regR); + break; + case 0xab: + cpu.regX = cpu.regR; + if (cpu.flagX) + cpu.regX &= 0xff; + upNZX(cpu.regX); + break; + case 0x44: + push2r(readW_PC()); + break; + case 0x54: + push2r(readBW()); + break; + case 0x82: + n = readB(); + push2r(cpu.regPC + n); + break; + case 0x3b: + cpu.regX = popXr(); + upNZX(cpu.regX); + break; + case 0x6b: + cpu.regA = popMr(); + upNZ(cpu.regA); + break; + case 0x7b: + cpu.regY = popXr(); + upNZX(cpu.regY); + break; + case 0x1b: + pushXr(cpu.regX); + break; + case 0x4b: + pushMr(cpu.regA); + break; + case 0x5b: + pushXr(cpu.regY); + break; + case 0x0b: + push2r(cpu.regI); + break; + case 0x2b: + cpu.regI = pop2r(); + upNZX(cpu.regI); + break; + case 0x5c: + cpu.regI = cpu.regX; + upNZX(cpu.regX); + break; + case 0xdc: + cpu.regX = cpu.regI; + if (cpu.flagX) + cpu.regX &= 0xff; + upNZX(cpu.regX); + break; + case 0x02: + cpu.regPC = readW(cpu.regI); + cpu.regI += 2; + break; + case 0x42: + if (cpu.flagM) + { + cpu.regA = readMem(cpu.regI); + cpu.regI += 1; + } + else + { + cpu.regA = readW(cpu.regI); + cpu.regI += 2; + } + break; + case 0x22: + push2r(cpu.regI); + cpu.regI = (cpu.regPC + 2); + cpu.regPC = readW(cpu.regPC); + break; + case 0x0f: + i_mul(readM(readB())); + break; + case 0x1f: + i_mul(readM(readBX())); + break; + case 0x2f: + i_mul(readM(readW_PC())); + break; + case 0x3f: + i_mul(readM(readWX())); + break; + case 0x4f: + i_div(readM(readB())); + break; + case 0x5f: + i_div(readM(readBX())); + break; + case 0x6f: + i_div(readM(readW_PC())); + break; + case 0x7f: + i_div(readM(readWX())); + break; + case 0x8f: + cpu.regD = 0; + cpu.regB = 0; + break; + case 0x9f: + cpu.regD = ((cpu.regA & negM()) > 0 ? 0xffff : 0); + cpu.regB = (cpu.regD & 0xff); + break; + case 0xaf: + cpu.regA = cpu.regD; + if (cpu.flagM) + cpu.regA &= 0xff; + upNZ(cpu.regA); + break; + case 0xbf: + if (cpu.flagM) + cpu.regD = (cpu.regA | cpu.regB << 8); + else + { + cpu.regD = cpu.regA; + } + upNZ(cpu.regA); + break; + case 0xcf: + cpu.regD = popM(); + break; + case 0xdf: + pushM(cpu.regD); + break; + case 0xef: + i_mmu(readB()); + break; + } +} + +void emulateframe() +{ + int i = 0; + + cpu.rbTimeout = 0; + cpu.waiTimeout = 0; + cpu.brk = 0; + cpu.cycles += cpu.cycles_per_tick; + cpu.ticks ++; + if (cpu.cycles > 100000) + cpu.cycles = 100000; + + while ((cpu.cycles > 0) && (!cpu.waiTimeout) && (!cpu.rbTimeout) && (!cpu.brk)) + { + cpu.cycles --; + executeInsn(); + + i = 0; + while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x1ffff) != (cpu.regPC | 0x10000)) ) + i++; + + if (i <= cpu.breakpoint_count) // breakpoint hit + { + cpu.cycles = 0; + cpu.brk = 1; + } + } +} diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..d895ab1 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,262 @@ +#include +#include + +#include "video/gbuffer.h" +#include "memory/memory.h" +#include "emubase.h" +#include "cpu/65el02.h" +#include "debug.h" +#include "monitor.h" + +//--------------------------------------------------------------------------- +int mempos = 0; +//--------------------------------------------------------------------------- +char * +int2bin8(int data) +{ + static char result[9]; + int qi; + + memset(&result, 0x00, sizeof(result)); + for (qi = 0; qi <= 7; qi++) + { + result[7 - qi] = 0x30 + ((data >> qi) & 1); + } + return result; +} + +//--------------------------------------------------------------------------- +void +showdebug() +{ + char tempstring[256]; + +// sprintf(tempstring," NV-BDIZC - AC %04X - RX %04X - RY %04X",cpu.regA,cpu.regX,cpu.regY); + sprintf(tempstring, "ENVMXDIZC - AC %04X - X %04X - Y %04X", cpu.regA, cpu.regX, cpu.regY); + drawstring(82, 3, tempstring, 0x01, 0x00, rom_charset); + + sprintf(tempstring, "%d%s - SP %04X - IP %04X - I %04X", cpu.flagE, int2bin8(getFlags()), cpu.regSP, cpu.regPC, cpu.regI); + drawstring(82, 4, tempstring, 0x01, 0x00, rom_charset); + + sprintf(tempstring, "SR %04X - B %04X - D %04X", cpu.regR, cpu.regB, cpu.regD); + drawstring(94, 5, tempstring, 0x01, 0x00, rom_charset); + + sprintf(tempstring, "MMU enable %02x - device %02X - offset %04X", cpu.mmuEnRB, cpu.mmuRBA, cpu.mmuRBB); + drawstring(82, 6, tempstring, 0x01, 0x00, rom_charset); +} + +//--------------------------------------------------------------------------- +void +showmemory(int memorypos) +{ + int qi, qj; + unsigned char tempstring[256]; + unsigned char tempreg; + + for (qi = 0; qi < 16; qi++) + { + sprintf(tempstring, "%04X ", memorypos & 0xffff); + for (qj = 0; qj < 8; qj++) + { + tempreg = mem_load(memorypos++); +// tempreg=ram[(memorypos++)&0xffff]; + + sprintf(tempstring, "%s%02X ", tempstring, tempreg); + + drawchar(113 + qj, 34 + qi, tempreg, 0x01, 0x00, rom_charset); + } + drawstring(82, 34 + qi, tempstring, 0x01, 0x00, rom_charset); + } +} + +//--------------------------------------------------------------------------- +int +getinst(char *str, int ip) +{ + char tempstring2[128]; + int opc, mode; + char *label = NULL; + + mode = (cpu.flagX << 1) | cpu.flagM; + opc = mem_load(ip); + + switch (codesizetable[addrmode[mode][opc]]) + { + case 1: + { + sprintf(tempstring2, "%02X ", opc); + break; + } + case 2: + { + sprintf(tempstring2, "%02X %02X ", opc, mem_load(ip + 1)); + break; + } + case 3: + { + sprintf(tempstring2, "%02X %02X %02X ", opc, mem_load(ip + 1), mem_load(ip + 2)); + break; + } + } + + sprintf(str, "%04X %s %s ", ip, tempstring2, opcodes[opc]); + *tempstring2 = 0; + + switch (addrmode[mode][opc]) + { + case 0: + { + break; + } + case 1: + { + sprintf(tempstring2, "($%02X,x) ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 2: + { + sprintf(tempstring2, "$%02X ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 3: + { + sprintf(tempstring2, "$%02X%02X ", mem_load(ip + 2), mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1) + (mem_load(ip + 2) << 8)); + break; + } + case 4: + { + sprintf(tempstring2, "($%02X),y ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 5: + { + sprintf(tempstring2, "$%02X,x ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 6: + { + sprintf(tempstring2, "$%02X%02X,y ", mem_load(ip + 2), mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1) + (mem_load(ip + 2) << 8)); + break; + } + case 7: + { + sprintf(tempstring2, "$%02X%02X,x ", mem_load(ip + 2), mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1) + (mem_load(ip + 2) << 8)); + break; + } + case 8: + { + sprintf(tempstring2, "$%04X ", ip + 2 + (signed char) mem_load(ip + 1)); + label = getlabel(ip + 2 + (signed char) mem_load(ip + 1)); + break; + } + case 9: + { + sprintf(tempstring2, "($%02X%02X) ", mem_load(ip + 2), mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1) + (mem_load(ip + 2) << 8)); + break; + } + case 10: + { + sprintf(tempstring2, "$%02X,y ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 11: + { + sprintf(tempstring2, "#$%02X ", mem_load(ip + 1)); + break; + } + case 12: + { + sprintf(tempstring2, "$%02X%02X ", mem_load(ip + 2), mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1) + (mem_load(ip + 2) << 8)); + break; + } + case 13: + { + sprintf(tempstring2, "$%02X,s ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 14: + { + sprintf(tempstring2, "($%02X,s),y", mem_load(ip + 1)); + break; + } + case 15: + { + sprintf(tempstring2, "($%02X) ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 16: + { + sprintf(tempstring2, "$%02X,r ", mem_load(ip + 1)); + label = getlabel(mem_load(ip + 1)); + break; + } + case 17: + { + sprintf(tempstring2, "($%02X,r),y", mem_load(ip + 1)); + break; + } + case 18: + { + sprintf(tempstring2, "#$%02X%02X ", mem_load(ip + 2), mem_load(ip + 1)); + break; + } + + } + + if (label != NULL) + { + if (*label) + { + strcat(tempstring2, ";"); + strcat(tempstring2, label); + } + } + + strcat(str, tempstring2); + + return (codesizetable[addrmode[mode][opc]]); +} + +void +showinst(int memorypos, struct cpustruct cpu) +{ + int qi,i = 0; + int opc, temp_ip, mode; + char tempstring[256]; + char tempstring2[32]; + temp_ip = memorypos; + + mode = (cpu.flagX << 1) | cpu.flagM; + + for (qi = 1; qi < 25; qi++) + { + getinst(tempstring, temp_ip); + strcat(tempstring," "); + tempstring[42] = 0x00; + + opc = mem_load(temp_ip); + + i = 0; + while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x1ffff) != (temp_ip | 0x10000)) ) + i++; + + if (i <= cpu.breakpoint_count) // breakpoint hit + drawstring(82, 7 + qi, tempstring, 0x01, 0x02, rom_charset); + else + drawstring(82, 7 + qi, tempstring, 0x01, 0x00, rom_charset); + + temp_ip = temp_ip + codesizetable[addrmode[mode][opc]]; + } +} diff --git a/src/display/display.c b/src/display/display.c new file mode 100644 index 0000000..7b1a1fd --- /dev/null +++ b/src/display/display.c @@ -0,0 +1,196 @@ +#include +#include +#include + +#include "display/display.h" +#include "screen.h" + +void blitter(int id) +{ + int i, j; + int w = displays[id].regs[12]; + int h = displays[id].regs[13]; + + int sy = displays[id].regs[9], sx = displays[id].regs[8]; + int dy = displays[id].regs[11], dx = displays[id].regs[10]; + + + if ((id <0) && (id >= MAX_DISPLAY)) + return; + + if (screens[id] == NULL) + return; + + + if (displays[id].regs[7] == 0) + return; + + if (w > (80 - dx)) + w = 80 - dx; + if (h > (50 - dy)) + h = 50 - dy; + + if ((w < 0) || (h < 0)) + { + displays[id].regs[7] = 0; + return; + } + + switch (displays[id].regs[7]) + { + case 1: + for (j = 0; j < h; j++) + for (i = 0; i < w; i++) + if (((j + dy) < 50) && ((i + dx) < 80)) + { + screens[id]->chars.rowcol[j + dy][i + dx] = displays[id].regs[8]; + if (screens[id]->type) + screens[id]->attributes.rowcol[j + dy][i + dx] = displays[id].regs[9]; + } + displays[id].regs[7] = 0; + return; + case 2: + for (j = 0; j < h; j++) + for (i = 0; i < w; i++) + if (((j + dy) < 50) && ((i + dx) < 80)) + screens[id]->chars.rowcol[j + dy][i + dx] ^= 0x80; + displays[id].regs[7] = 0; + return; + } + + if (w > (80 - sx)) + w = 80 - sx; + if (h > (50 - sy)) + h = 50 - sy; + + if ((w < 0) || (h < 0)) + { + displays[id].regs[7] = 0; + return; + } + + if (displays[id].regs[7] == 3) + { + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if (((j + sy) < 50) && ((i + sx) < 80) && ((j + dy) < 50) && ((i + dx) < 80)) + { + screens[id]->chars.rowcol[j + dy][i + dx] = screens[id]->chars.rowcol[j + sy][i + sx]; + if (screens[id]->type) + screens[id]->attributes.rowcol[j + dy][i + dx] = screens[id]->attributes.rowcol[j + sy][i + sx]; + } + } + } + displays[id].regs[7] = 0; + } +} + + +void init_displays() +{ + memset(&displays,0x00,sizeof(displays)); +} + +void reset_display(int id) +{ + if ((id >=0) && (id < MAX_DISPLAY)) + { + if (screens[id] != NULL) + { + displays[id].regs[3] = 2; + displays[id].regs[4] = 0; + displays[id].regs[5] = 0; + displays[id].regs[6] = 0; + + memset(screens[id]->chars.linear,0x20,SCR_SIZE); + scrattrfill(id, 0xbd); + } + } +} + +void disp_store(int id, int ptr, unsigned char value) +{ + if ((id >=0) && (id < MAX_DISPLAY)) + { + if (screens[id] != NULL) + { + if (ptr < 16) + { + if ((ptr == 0x04) || (ptr == 0x05)) + { + displays[id].regs[ptr] = value & 0x0f; + } + else if (ptr != 0x06) + { + displays[id].regs[ptr] = value; + + if (ptr == 0x01) screens[id]->cx = value; + if (ptr == 0x02) screens[id]->cy = value; + if (ptr == 0x03) screens[id]->blink = value; + } + } + else if ((ptr >= 0x10) && (ptr < 0x60)) + { + if (displays[id].regs[0] < 50) + screens[id]->chars.rowcol[displays[id].regs[0]][ptr - 0x10] = value; + } + else if ((screens[id]->type == 1) && (ptr >= 0x60) && (ptr < 0xb0)) + { + if (displays[id].regs[0] < 50) + screens[id]->attributes.rowcol[displays[id].regs[0]][ptr - 0x60] = value; + } + } + } +} + +unsigned char disp_load(int id, int ptr) +{ + if ((id >=0) && (id < MAX_DISPLAY)) + { + if (screens[id] != NULL) + { + if (ptr < 16) + { + if (ptr == 0x06) + return displays[id].kbbuf[displays[id].regs[4]]; + + return displays[id].regs[ptr]; + } + else if ((ptr >= 0x10) && (ptr < 0x60)) + { + if (displays[id].regs[0] < 50) + return screens[id]->chars.rowcol[displays[id].regs[0]][ptr - 0x10]; + } + else if ((screens[id]->type == 1) && (ptr >= 0x60) && (ptr < 0xb0)) + { + if (displays[id].regs[0] < 50) + return screens[id]->attributes.rowcol[displays[id].regs[0]][ptr - 0x60]; + } + else if (ptr == 0xff) + return screens[id]->type; + } + } + return 0; + +} + +unsigned char disp_key(int id, unsigned char ch) +{ + int np; + + if ((id >=0) && (id < MAX_DISPLAY)) + { + if (screens[id] != NULL) + { + np = (displays[id].regs[5] + 1) & 0x0f; + if (np != displays[id].regs[4]) + { + displays[id].kbbuf[displays[id].regs[5] & 0x0f] = ch; + displays[id].regs[5] = np; + displays[id].regs[6] = displays[id].kbbuf[displays[id].regs[4] & 0x0f]; + } + } + } +} diff --git a/src/drive/drive.c b/src/drive/drive.c new file mode 100644 index 0000000..aa6b21f --- /dev/null +++ b/src/drive/drive.c @@ -0,0 +1,209 @@ +#include +#include +#include + +#include "drive/drive.h" + +int drive_io_penality = 1; + +void drive_set(int id, char *name) +{ + int qi; + + if ((id >= 0) && (id <256)) + { + if(drives[id].name) + free(drives[id].name); + + drives[id].name = strdup(name); + memset(drives[id].serial,0x00,sizeof(drives[id].serial)); + + if (drives[id].name) + { + + if (!strncasecmp(drives[id].name,"disk_",5)) + { + qi = 0; + while ( (qi<16) && + ( ((toupper(drives[id].name[5+qi]) >='A') && + (toupper(drives[id].name[5+qi]) <='Z')) || + ((toupper(drives[id].name[5+qi]) >='0') && + (toupper(drives[id].name[5+qi]) <='9')) ) ) + { + drives[id].serial[qi] = drives[id].name[5+qi]; + } + } + } + else + { + // printf("strdup() failed\n"); + } + } + +} + +void drive(int id) +{ + FILE *diskfile; + int sector, size; + + unsigned char dummy[0x80]; + char tempstring[256]; + + switch (drives[id].command) + { + case 0x01: + memset(drives[id].buffer, 0x00, 128); + if (drives[id].name) + strncpy(drives[id].buffer,drives[id].name,127); + + drives[id].command = 0x00; + break; + + case 0x02: + snprintf(tempstring,256,"%s.img",drives[id].buffer); + drive_set(id, tempstring); + + drives[id].type = 0; + drives[id].command = 0x00; + break; + + case 0x03: + memset(drives[id].buffer, 0x00, 128); + + if (drives[id].type) + { + strcpy(drives[id].buffer,"System Disk"); + } + else + { + if (drives[id].serial) + memcpy(drives[id].buffer, drives[id].serial, sizeof(drives[id].serial)); + else if (drives[id].name) + strncpy(drives[id].buffer, drives[id].name,127); + } + + drives[id].command = 0x00; + break; + + case 0x04: + if (drives[id].sector >= 2048) + drives[id].command = 0xff; + + else if (drives[id].name) + { + // printf("drive %d name %s\n", id, drives[id].name); + if ((diskfile = fopen(drives[id].name, "rb")) == NULL) + { + // printf("open failed\n"); + drives[id].command = 0xff; + break; + } + + fseek(diskfile, drives[id].sector << 7, SEEK_SET); + size = fread(drives[id].buffer, 1, 0x80, diskfile); + fclose(diskfile); + + // printf("drive %d read sector %d success, size = %d\n",id,drives[id].sector,size); + + if (size != 0x80) + drives[id].command = 0xff; + else + drives[id].command = 0x00; + + } + else + { + drives[id].command = 0xff; + } + break; + + case 0x05: + if (drives[id].sector >= 2048) + drives[id].command = 0xff; + else if (drives[id].name && !drives[id].type) + { + if ((diskfile = fopen(drives[id].name, "rb+")) == NULL) + { + if ((diskfile = fopen(drives[id].name, "wb")) == NULL) + { + drives[id].command = 0xff; + break; + } + } + + memset(dummy,0x00,sizeof(dummy)); + + fseek(diskfile, 0, SEEK_END); + size = ftell(diskfile); + while (size < (drives[id].sector << 7)) + { + size += fwrite(&dummy, 1, 0x80, diskfile); + } + + fseek(diskfile, drives[id].sector << 7, SEEK_SET); + size = fwrite(&drives[id].buffer, 1, 0x80, diskfile); + fclose(diskfile); + if (size != 0x80) + drives[id].command = 0xff; + else + drives[id].command = 0x00; + } + else + drives[id].command = 0xff; + break; + + default: + break; + } + +} + +void drive_store(int id, int ptr, unsigned char value) +{ + if ((id >= 0) && (id <256)) + { + if ((ptr >= 0) && (ptr < 0x80)) + drives[id].buffer[ptr] = value; + + else if (ptr == 0x80) + drives[id].sector = (drives[id].sector & 0xff00) | value; + + else if (ptr == 0x81) + drives[id].sector = (drives[id].sector & 0xff) | (value << 8); + + else if (ptr == 0x82) + { + drives[id].command = value; + + if (!drive_io_penality) + drive(id); + } + } +} + +unsigned char drive_load(int id, int ptr) +{ + if ((id >= 0) && (id < 256)) + { + if ((ptr >= 0) && (ptr < 0x80)) + return drives[id].buffer[ptr]; + + else if (ptr == 0x80) + return drives[id].sector & 0xff; + + else if (ptr == 0x81) + return (drives[id].sector >> 8) & 0xff; + + else if (ptr == 0x82) + return drives[id].command; + } + + return 0; +} + +void drive_type(int id, int type) +{ + if ((id >= 0) && (id <256)) + drives[id].type = type; +} diff --git a/src/emubase.c b/src/emubase.c new file mode 100644 index 0000000..697995f --- /dev/null +++ b/src/emubase.c @@ -0,0 +1,316 @@ +#include +#include +#include + +#include + +#include "memory/memory.h" +#include "cpu/65el02.h" +#include "display/display.h" +#include "video/gbuffer.h" +#include "drive/drive.h" +#include "emubase.h" +#include "emuversion.h" +#include "debug.h" +#include "monitor.h" +#include "options.h" + +#include "screen.h" + +int load_address = -1; +//--------------------------------------------------------------------------- +int start_pc = -1; +int init_breakpoint = -1; +int init_cycles_per_tick = -1; +//--------------------------------------------------------------------------- +char emulation_run = 1; + +void loadprogram(char *programname) +{ + FILE *f; + + if (*programname) + { + if ((f = fopen(programname, "rb")) != NULL) + { + fseek(f, 0, SEEK_SET); + fread(&load_address, 1, 2, f); + fread(&ram[load_address], 1, (0x10000 - load_address), f); + fclose(f); + } + else + { + printf("File open error! [%s]\n", programname); + } + } +} + +//--------------------------------------------------------------------------- +void showall(struct cpustruct cpu) +{ + char tempstring[256]; + + displayscreen(cpu.byte1); + + showdebug(); + showmemory(mempos); + showinst(cpu.regPC,cpu); + + drawstring(0, C_SIZEY-1, "\r F1-Help F2-Options F3-Peripherals F4-IO extenders F6-Built-in monitor", 0x0f, 0x09, rom_charset); + + if (emulation_run) + sprintf(tempstring, "F9-trace mode emulation running"); + else + sprintf(tempstring, "F9-run F11-step trace mode"); + + drawstring(C_SIZEX-strlen(tempstring)-2, C_SIZEY-1, tempstring, 0x0f, 0x09, rom_charset); + + updateptc(); +} + +void reset() +{ + coldBootCPU(); + if (init_cycles_per_tick > 0) + cpu.cycles_per_tick = init_cycles_per_tick; + + if (start_pc >= 0) + cpu.regPC = start_pc; + + reset_display(cpu.byte1); + + ram[0] = cpu.byte0; + ram[1] = cpu.byte1; + + memcpy(&ram[0x400],&bootcode,sizeof(bootcode)); +} + +//--------------------------------------------------------------------------- +void emulation() +{ + + int ch, np, mode; + int qi, lastframe; + char quit = 0, result; + int tempreg, last_tick; + char tempstring[64]; + + FILE *f; + + if ((f = fopen("/usr/share/rpc/roms/charset.rom", "rb")) != NULL) + { + fseek(f, 0, SEEK_SET); + fread(rom_charset, 1, sizeof(rom_charset), f); + fclose(f); + } + else + { + printf("missing charset rom (roms/charset.rom)\n"); + return; + } + + if ((f = fopen("/usr/share/rpc/roms/rpcboot.bin", "rb")) != NULL) + { + fseek(f, 0, SEEK_SET); + fread(&bootcode, 1, sizeof(bootcode), f); + fclose(f); + } + else + { + printf("missing bootcode (roms/rpcboot.bin)\n"); + return; + } + + memset(&cpu, 0x00, sizeof(cpu)); + memset(&ioextender, 0x00, sizeof(ioextender)); + memset(&peripherals, 0x00, sizeof(peripherals)); + memset(&drives, 0x00, sizeof(drives)); + + readoptions(); + + coldBootCPU(); + + if (!peripherals[cpu.byte0]) + peripherals[cpu.byte0] = 3; + if (!peripherals[cpu.byte1]) + peripherals[cpu.byte1] = 1; + + drive_set(cpu.byte0, defdiskname); + drive_type(cpu.byte0, defdisktype); + + init_displays(); + initscreen(); + + for (qi=0; qi<256; qi++) + { + if ((peripherals[qi] == 1) || (peripherals[qi] == 2)) + { + openscreen(qi); + scrtype(qi, peripherals[qi]-1); + } + } + + reset(); + + moninit(); + optinit(); + + memset(cpu.breakpoints, 0x00, sizeof(cpu.breakpoints)); + + cpu.breakpoint_count = 0; + if (init_breakpoint >= 0) + cpu.breakpoints[cpu.breakpoint_count++] = init_breakpoint | 0x10000; + + for (qi=0; qi= 0) + { + ch = lastkeysym; + +// sprintf(tempstring,"symkey: %04x mod: %04x",ch,lastkeymod); +// drawstring(0, 52, tempstring, 0x01, 0x00, rom_charset); + + if ((ch == SDLK_PAUSE) || (ch == SDLK_F6)) + { + quit = monitor(); + } + + if (ch == SDLK_F1) + quit = help(); + + if (ch == SDLK_F2) + quit = options(); + + if (ch == SDLK_F3) + quit = optperipherals(); + + if (ch == SDLK_F4) + quit = optiox(-1); + + if ((ch == SDLK_ESCAPE) && (lastkeymod & KMOD_SHIFT)) + quit = 1; // shift+esc + if ((ch == SDLK_x) && (lastkeymod & KMOD_LALT)) + quit = 1; // alt-x + if ((ch == SDLK_F4) && (lastkeymod & KMOD_LALT)) + quit = 1; // alt-x + + if (ch == SDLK_F9) + { // F9 + emulation_run = emulation_run ^ 1; + showall(cpu); + } + + if ( (ch == SDLK_F11) && (!emulation_run) ) + { + executeInsn(); + showall(cpu); + } + + if ( (ch == SDLK_F12) && (!emulation_run) ) + { + mode = (cpu.flagX << 1) | cpu.flagM; + cpu.breakpoints[0]=(cpu.regPC + codesizetable[addrmode[mode][mem_load(cpu.regPC)]]) | 0x10000; + emulation_run=1; + } + + if (ch == SDLK_PAGEUP) + { // PAGEUP + if ((lastkeymod & KMOD_SHIFT) != KMOD_SHIFT) + { + mempos = (mempos - 0x08) & 0xffff; + showmemory(mempos); + } + else + { + mempos = (mempos - 0x80) & 0xffff; + showmemory(mempos); + } + showall(cpu); + } + + if (ch == SDLK_PAGEDOWN) + { // PAGEDOWN + if ((lastkeymod & KMOD_SHIFT) != KMOD_SHIFT) + { + mempos = (mempos + 0x08) & 0xffff; + showmemory(mempos); + } + else + { + mempos = (mempos + 0x80) & 0xffff; + showmemory(mempos); + } + showall(cpu); + } + + if ((ch == SDLK_r) && (lastkeymod & KMOD_LALT)) + { + reset(); + } + + ch = lastkey; + + if ((ch > 0) && (ch < 128) && !(lastkeymod & KMOD_LALT)) + { + if (ch != 27) // ignore ESC + { + disp_key(cpu.byte1, ch); + } + } + + } + + if (lastkey == -2) + quit = 1; + + } + + } + + shutdownscreen(); +} + +//--------------------------------------------------------------------------- diff --git a/src/memory/memory.c b/src/memory/memory.c new file mode 100644 index 0000000..d9c1af7 --- /dev/null +++ b/src/memory/memory.c @@ -0,0 +1,93 @@ +#include "memory/memory.h" +#include "cpu/65el02.h" +#include "display/display.h" +#include "drive/drive.h" + +int memory_max = 0x2000; + +// ---------------------------------------------------------------------------- +void +mem_store(int ptr, unsigned char value) +{ + int id = cpu.mmuRBA & 0xff; + ptr &= 0xffff; + +// printf("%d %04x\n",cpu.mmuEnRB,cpu.mmuRBB); + + if ((cpu.mmuEnRB) && (ptr >= cpu.mmuRBB) && (ptr < cpu.mmuRBB + 256)) + { + ptr = ptr - cpu.mmuRBB; + + switch (peripherals[id]) + { + case 1: + case 2: + disp_store(id, ptr, value); + break; + case 3: + drive_store(id, ptr, value); + break; + case 4: + if (ptr == 2) + ioextender[id].output = (ioextender[id].output & 0xff00) | value; + if (ptr == 3) + ioextender[id].output = (ioextender[id].output & 0xff) | value << 8; + break; + + } + } + else + { + if (ptr < memory_max) + ram[ptr] = value; + } +} + +// ---------------------------------------------------------------------------- +unsigned char +mem_load(int ptr) +{ + int id = cpu.mmuRBA & 0xff; + ptr &= 0xffff; + + if ((cpu.mmuEnRB) && (ptr >= cpu.mmuRBB) && (ptr < cpu.mmuRBB + 256)) + { + ptr = ptr - cpu.mmuRBB; + + + switch (peripherals[id]) + { + case 1: + case 2: + return disp_load(id, ptr); + break; + case 3: + return drive_load(id, ptr); + break; + case 4: + if (ptr == 0) + return ioextender[id].input & 0xff; + if (ptr == 1) + return (ioextender[id].input >> 8) & 0xff; + if (ptr == 2) + return ioextender[id].output & 0xff; + if (ptr == 3) + return (ioextender[id].output >> 8) & 0xff; + break; + + } + + return 0; + + } + else + { + if (ptr < memory_max) + return ram[ptr]; + else + return 0; + } + +} + +// ---------------------------------------------------------------------------- diff --git a/src/monitor.c b/src/monitor.c new file mode 100644 index 0000000..77aa248 --- /dev/null +++ b/src/monitor.c @@ -0,0 +1,471 @@ +#include +#include +#include + +#include + +#include "video/gbuffer.h" +#include "cpu/65el02.h" +#include "memory/memory.h" +#include "debug.h" +#include "calc.h" +#include "monitor.h" +#include "screen.h" +#include "display/display.h" + +static char *commands[] = {"BA","BR","IO","RT", + "D","M","B","T","LL","CT"}; +static int commands_count = sizeof(commands)/sizeof(commands[0]); + +static unsigned short a2l[0x10000]; // labels pointer; +static unsigned short p2a[0x10000]; +static int labelptrs[0x10000]; +static int maxptrs = 0; + +static char labels[0x100000]; +static int maxlabels = 0; + +void moninit() +{ + openscreen(SCR_ID_MONITOR); +} + +char *getcmd(char *to, char *from) +{ + int i,j,size = strlen(from); + + *to = 0x00; + + while (*from == 0x20) + *from++; + + i = 0; + while (i0)) + { + strcpy(to,commands[i]); + from += strlen(commands[i]); + break; + } + i++; + } + while (*from == 0x20) + *from++; + + return from; + +} + +char *getstr(char *to, char *from, int flag) +{ + if (flag == 0) + { + while (*from && (*from != ' ')) + { + *to++ = toupper(*from++); + } + } + else if (flag == 1) + { + while (*from && (toupper(*from) >= 'A') && (toupper(*from) <= 'Z')) + { + *to++ = toupper(*from++); + } + } + else if (flag == 2) + { + while (*from && (*from != ' ') && (*from != ',') ) + { + *to++ = toupper(*from++); + } + } + + *to = 0; + + while (*from == ' ') + from++; + + return from; +} + +void do_command(char *str) +{ + char cmd[256]; + char tempstring[256]; + + double tempdouble; + int from,to,val,qi; + + str = getcmd(cmd,str); + +// scrprintf(SCR_ID_MONITOR,"command: [%s] param: [%s]\n",cmd,str); + + if (strcmp(cmd,"BR") == 0) + { + str = getstr(cmd,str,0); + if (*cmd) + { + calc(cmd, &tempdouble); + val = (int)tempdouble; + } + else + val = 0; + + if ((val>=0) && (val= 0x10000) + { + scrprintf(SCR_ID_MONITOR,"Breakpoint %d: $%04x ", qi, cpu.breakpoints[qi] & 0xffff); + if (cpu.breakpoints[qi] & 0x10000) + scrprintf(SCR_ID_MONITOR,"X"); + else + scrprintf(SCR_ID_MONITOR," "); + + if (cpu.breakpoints[qi] & 0x20000) + scrprintf(SCR_ID_MONITOR,"R"); + else + scrprintf(SCR_ID_MONITOR," "); + + if (cpu.breakpoints[qi] & 0x40000) + scrprintf(SCR_ID_MONITOR,"W"); + else + scrprintf(SCR_ID_MONITOR," "); + + scrprintf(SCR_ID_MONITOR," %s\n",getlabel(cpu.breakpoints[qi] & 0xffff)); + val++; + } + } + if (!val) + scrprintf(SCR_ID_MONITOR,"No breakpoints set\n"); + + } + else if (strcmp(cmd,"T") == 0) + { + scrprintf(SCR_ID_MONITOR,"Total tick count: %d\n", cpu.ticks); + } + else if (strcmp(cmd,"RT") == 0) + { + cpu.ticks=0; + scrprintf(SCR_ID_MONITOR,"Total tick count reseted\n"); + } + else if (strcmp(cmd,"D") == 0) + { + str = getstr(cmd,str,0); + sprintf(tempstring,"$%s",cmd); + calc(tempstring, &tempdouble); + from = ((int)tempdouble) & 0xffff; + + str = getstr(cmd,str,0); + if (strlen(cmd)>0) + { + sprintf(tempstring,"$%s",cmd); + calc(tempstring, &tempdouble); + to = (int)tempdouble; + } + else + to += from + 0x20; + + while (from=0) && (fromtype ^= 1; + scrprintf(SCR_ID_MONITOR,"display %d mode changed to %d\n",from,screens[from]->type); + } + else + scrprintf(SCR_ID_MONITOR,"display %d not available\n",from); + } + else + { + scrprintf(SCR_ID_MONITOR,"invalid display id\n",from); + } + } + + else if (*str) + { + scrprintf(SCR_ID_MONITOR,"Unknown command [%s]\n\n",cmd); + scrprintf(SCR_ID_MONITOR," B\t\tCheck breakpoint\n"); + scrprintf(SCR_ID_MONITOR," BA xxxx\tAdd breakpoint\n"); + scrprintf(SCR_ID_MONITOR," BR\t\tRemove breakpoint\n"); + scrprintf(SCR_ID_MONITOR," D xxxx (yyyy)\tAssembly dump from $xxxx (to $yyyy)\n"); + scrprintf(SCR_ID_MONITOR," IO x,(val)\tDump IO Expander number x (and set input to VALue)\n"); + scrprintf(SCR_ID_MONITOR," M xxxx\t\tSet memory dump address to $xxxx\n"); + scrprintf(SCR_ID_MONITOR," LL (x)\t\tList 25 labels (from element x)\n"); + scrprintf(SCR_ID_MONITOR," CT (x)\t\tToggles display (id x) type (monochrome/color)\n\n"); + } +} + +int monitor() +{ + int quit=0; + int esc=0; + int last_tick; + char tempstring[256]; + char *ptr = tempstring; + + sprintf(tempstring, "\rmonitor mode, hit ESC to exit"); + drawstring(0, C_SIZEY-1, tempstring, 0x01, 0x00, rom_charset); + + scrprintf(SCR_ID_MONITOR,"\n%s\n",tempstring); + + *tempstring = 0; + + while (!quit && !esc) + { + + last_tick = timer_tick; + + displayscreen(SCR_ID_MONITOR); + updateptc(); + + while (last_tick == timer_tick) + SDL_Delay(1); + + while (getkeys()) + { + if (lastkeysym >= 0) + { + if (lastkeysym == SDLK_ESCAPE) + esc = 1; + if ((lastkeysym == SDLK_x) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-x + if ((lastkeysym == SDLK_F4) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-f4 + } + + if (lastkey > 0) + { + if (lastkey>=0x20) + { + if (ptrtempstring) + *(--ptr) = 0x00; + scrprintf(SCR_ID_MONITOR,"%c",lastkey); + } + if ((lastkey == 13) || (lastkey == 10)) + { + scrprintf(SCR_ID_MONITOR,"\n"); + do_command(tempstring); + ptr = tempstring; + *tempstring = 0; + } + } + } + + if (lastkey == -2) + quit = 1; + } + } + return quit; +} + +void cleanstring(char *str) +{ + char *dst = str; + while (*str) + { + if (*str >= 0x20) + *dst++ = *str; + *str++; + } + + *dst = 0x00; + +} +char *getlabelfromstr(char *label, char *line) +{ + char *min = label; + + while (*line == 0x20) + *line ++; + + while ((*line != 0x00) && (*line != '=')) + *label ++ = *line++; + + while (*line == '=') + *line ++; + + while ((label>min) && (*(label-1) == 0x20)) + *label --; + + *label = 0x00; + return line; + +} + +void monitor_listing(char *fname) +{ + FILE *f; + char line[256]; + char label[256]; + char addr[256]; + char *ptr; + double tempdouble; + int tempint; + + if ((f = fopen(fname, "rb")) != NULL) + { + memset(&a2l, 0x00, sizeof(a2l)); + memset(&p2a, 0x00, sizeof(p2a)); + memset(&labels, 0x00, sizeof(labels)); + memset(&labelptrs, 0x00, sizeof(labelptrs)); + maxptrs = 0; + maxlabels = 1; // first is empty string; + + printf("reading listing file: %s\n",fname); + while (!feof(f)) + { + fgets(line, sizeof(line), f); + cleanstring(line); + if (*line) + { + ptr = getlabelfromstr(label,line); + + while (*ptr == 0x20) + *ptr++; + + ptr = getstr(addr,ptr,0); + calc(addr, &tempdouble); + tempint = (int)tempdouble; +// printf("label: %s addr: %04x\n",label,tempint); + + if ((tempint) && (!a2l[tempint])) + { + a2l[tempint] = ++maxptrs; + p2a[maxptrs] = tempint; + strcpy(labels+maxlabels, label); + labelptrs[maxptrs] = maxlabels; + maxlabels += sizeof(label) + 1; + } + } + } + fclose(f); + } + else { + printf("listing file not found: %s\n",fname); + } + +} + +char *getlabel(int address) +{ + if (a2l[address]) + return labels + labelptrs[a2l[address]]; + else + return labels; +} + +int getaddress(char *label) +{ + int qi = 1, found = 1; + while ((qi < maxptrs) && found) + { + found = strcasecmp(label,&labels[labelptrs[qi]]); + if (found) qi++; + } + if (!found) + return p2a[qi]; + else + return -1; +} \ No newline at end of file diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..98ab6b1 --- /dev/null +++ b/src/options.c @@ -0,0 +1,1153 @@ +#include +#include +#include + +#include + +#include "video/gbuffer.h" +#include "display/display.h" +#include "cpu/65el02.h" +#include "memory/memory.h" +#include "drive/drive.h" +#include "monitor.h" +#include "screen.h" +#include "options.h" + +void peripherals_print(int id, char *str); +int peripherals_seth(int id, int key, int keysym); + +void options_print(int id, char *str); +int options_seth(int id, int key, int keysym); + +void saveoptions(); +int optdrive(int id); + +optionmenustruct option_menu[] = { + { 10, "Default (active) monitor id", 5, "default_monitor_id", NULL, options_print, options_seth}, + { 11, "Default disk drive id", 0, "default_drive_id", NULL, options_print, options_seth}, + { 0, NULL}, + { 1, "CPU Speed", 0, "cpu_speed", NULL, options_print, options_seth}, + { 2, "MMU type", 0, "mmu_type", NULL, options_print, options_seth}, + { 3, "IO penality", 0, "io_penality", NULL, options_print, options_seth}, + { 5, "Drive boost", 0, "drive_boost", NULL, options_print, options_seth}, + { 4, "Memory", 0, "memory_size", NULL, options_print, options_seth}, + { 0, NULL}, + { 12, "Stack pointer bug fix", 0, "spbugfix", NULL, options_print, options_seth}, + { 0, "(don't enable unless you"}, + { 0, " know what are you doing)"}, + { 0, NULL}, + { 100, "Peripherals -->", 0, NULL, NULL, NULL, options_seth}, + { 0, NULL}, + { 200, "Save settings", 0, NULL, NULL, NULL, options_seth}, + { 0, NULL}, + {1000, "Back", 0, NULL, NULL, NULL, options_seth}, + {-1} +}; + +optionmenustruct peripherals_menu[] = { + { 1, "Device id 1", 25, NULL, NULL, peripherals_print, peripherals_seth}, + { 2, "Device id 2", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 3, "Device id 3", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 4, "Device id 4", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 5, "Device id 5", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 6, "Device id 6", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 7, "Device id 7", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 8, "Device id 8", 0, NULL, NULL, peripherals_print, peripherals_seth}, + { 9, "Device id 9", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {10, "Device id 10", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {0, NULL}, + {11, "Device id 11", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {12, "Device id 12", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {13, "Device id 13", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {14, "Device id 14", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {15, "Device id 15", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {16, "Device id 16", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {17, "Device id 17", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {18, "Device id 18", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {19, "Device id 19", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {20, "Device id 20", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {0, NULL}, + {21, "Device id 21", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {22, "Device id 22", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {23, "Device id 23", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {24, "Device id 24", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {25, "Device id 25", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {26, "Device id 26", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {27, "Device id 27", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {28, "Device id 28", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {29, "Device id 29", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {30, "Device id 30", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {0, NULL}, + {31, "Device id 31", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {32, "Device id 32", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {33, "Device id 33", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {34, "Device id 34", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {35, "Device id 35", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {36, "Device id 36", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {37, "Device id 37", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {38, "Device id 38", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {39, "Device id 39", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {40, "Device id 40", 0, NULL, NULL, peripherals_print, peripherals_seth}, + {0, NULL}, + {1000, "Back", 0, NULL, NULL, NULL, options_seth}, + {-1} + +}; + +int last_iox = -1; + +void peripherals_print(int id, char *str) +{ + switch (peripherals[id] & 0xff) + { + case 0: strcpy(str, "-"); break; + case 1: strcpy(str, "monochrome monitor"); break; + case 2: strcpy(str, "color monitor"); break; + case 3: strcpy(str, "disk drive -->"); break; + case 4: strcpy(str, "io extender -->"); break; + default: break; + } +} + +void options_print(int id, char *str) +{ + switch(id) + { + case 1: + sprintf(str, "%dx", (cpu.cycles_per_tick / 1000)); + break; + case 2: + if (cpu.mmu_type == 0) + strcpy(str,"original"); + if (cpu.mmu_type == 1) + strcpy(str,"bigfoot"); + break; + + case 3: + if (!cpu.no_io_penality) + strcpy(str,"on"); + else + strcpy(str,"off"); + break; + + case 4: + sprintf(str,"%dkb",memory_max >> 10); break; + + case 5: + if (!drive_io_penality) + strcpy(str,"on"); + else + strcpy(str,"off"); + break; + + case 10: + sprintf(str, "%d", cpu.byte1); + return; + + case 11: + sprintf(str, "%d", cpu.byte0); + return; + + case 12: + if (!nospbug) + strcpy(str,"disabled"); + else + strcpy(str,"enabled"); + break; + + default: + *str = 0; + break; + } +} + +int peripherals_seth(int id, int key, int keysym) +{ + if (keysym == SDLK_RIGHT) + { + if (peripherals[id] < 4) + peripherals[id] ++; + else + peripherals[id] = 0; + + } + if (keysym == SDLK_LEFT) + { + if (peripherals[id] > 0) + peripherals[id] --; + else + peripherals[id] = 4; + } + + if ((peripherals[id] == 1) || (peripherals[id] == 2)) + { + openscreen(id); + scrtype(id,peripherals[id] - 1); + } + + if ( (peripherals[id] == 3) && ((key == 10) || (key == 13)) ) + { + return optdrive(id); + } + + if ( (peripherals[id] == 4) && ((key == 10) || (key == 13)) ) + { + return optiox(id); + } + + return 0; +} + +int options_seth(int id, int key, int keysym) +{ + int tmp; + +// scrprintf(SCR_ID_OPTIONS,"id: %d key: %d keysym: %d\n", id, key, keysym); +// displayscreen(SCR_ID_OPTIONS); +// updateptc(); +// SDL_Delay(1000); + + if ((key == 10) || (key == 13)) + { + if (id == 100) + return optperipherals(); + + if (id == 200) + { + saveoptions(); + return 0; + } + if (id == 1000) + return 1; + } + + if (keysym == SDLK_RIGHT) + { + + if (id == 1) + { + tmp = (cpu.cycles_per_tick / 1000); + if (tmp < 2) + tmp = 2; + else if (tmp < 5) + tmp = 5; + else if (tmp < 10) + tmp = 10; + else + tmp = 100; + + cpu.cycles_per_tick = tmp * 1000; + } + +// if (id == 2) +// cpu.mmu_type ^= 1; + + if (id == 3) + cpu.no_io_penality ^= 1; + + if (id == 4) /* MEMORY SIZE */ + { + tmp = (memory_max + 0x2000) & 0x1e000; + if (tmp > 0x10000) + tmp = 0x10000; + memory_max = tmp; + } + + if (id == 5) + drive_io_penality ^= 1; + + if (id == 10) + { + if (cpu.byte1 < 40) + cpu.byte1 ++; + openscreen(cpu.byte1); + } + + if (id == 11) + if (cpu.byte0 < 40) + cpu.byte0 ++; + + if (id == 12) + nospbug ^= 1; + + } + + + else if (keysym == SDLK_LEFT) + { + if (id == 1) /* CPU SPEED */ + { + tmp = (cpu.cycles_per_tick / 1000); + if (tmp > 10) + tmp = 10; + else if (tmp > 5) + tmp = 5; + else if (tmp > 2) + tmp = 2; + else + tmp = 1; + + cpu.cycles_per_tick = tmp * 1000; + } + +// if (id == 2) +// cpu.mmu_type ^= 1; + + if (id == 3) + cpu.no_io_penality ^= 1; + + if (id == 4) /* MEMORY SIZE */ + { + tmp = (memory_max - 0x2000) & 0x1e000; + if (tmp < 0x2000) + tmp = 0x2000; + memory_max = tmp; + } + + if (id == 5) + drive_io_penality ^= 1; + + if (id == 10) + { + if (cpu.byte1 > 1) + cpu.byte1 --; + openscreen(cpu.byte1); + } + + if (id == 11) + if (cpu.byte0 > 1) + cpu.byte0 --; + + if (id == 12) + nospbug ^= 1; + } + + return 0; +} + +void optinit() +{ + openscreen(SCR_ID_OPTIONS); + openscreen(SCR_ID_PERIPHERALS); +} + +int options_handler(int id, optionmenustruct *opts, char *hdr, int src) +{ + int quit = 0, esc = 0; + + int maxlen = 0, maxlen2 = 0; + int elems = 0, elem = 0, pos = 0, add = 0; + int last_tick = -1, tmp; + int redraw = 1, selected; + + char tempstring[256]; + + scrblink(id, 0); + drawstring(0, C_SIZEY-1, "\r Up/Down - Move Left/Right - Change Enter - Sub-options (-->) ESC - Back", 0x0f, 0x09, rom_charset); + + if (opts) + { + while (opts[pos].id>=0) + { + if (opts[pos].name) + { + tmp = strlen(opts[pos].name); + + if (maxlen < tmp) + maxlen = tmp; + + if (maxlen2 < (maxlen + opts[0].len + 4) ) + maxlen2 = maxlen + opts[0].len + 4; + } + elems++; + pos++; + } + + scrprintf(id, "\nelements: %d\tmax len: %d\n", elems, maxlen); + } + + pos = 0; + selected = -1; + + while (!quit && !esc) + { + + if ((redraw) && (opts)) + { + selected = -1; + + scrclr(id); + scrattr(id, 0x7b); + scrprintf(id, "%*s", SCR_COLS, ""); + scrxy(id, (80-strlen(hdr))/2, 0); + scrprintf(id, "%s", hdr); + + tmp = add; + while ((tmp + pos < elems) && (tmp < 46)) + { + if ((opts[tmp + pos].id >= 0) && (opts[tmp + pos].name)) + { + + if ((tmp + pos) == elem) + { + scrattr(id, 0xdb); + selected = elem; + } + + else + scrattr(id, 0xbd); + + scrxy(id, (80-maxlen2)/2, tmp + 2); + scrprintf(id, "%*s", maxlen2, ""); + scrxy(id, 1 + (80-maxlen2)/2 , tmp + 2); + scrprintf(id, "%s", opts[tmp + pos].name); + + if (opts[tmp + pos].print_handler) + { + opts[tmp + pos].print_handler(opts[tmp + pos].id, tempstring); + scrxy(id, maxlen2 - 1 - strlen(tempstring) + (80-maxlen2)/2 , tmp + 2); + + if ((tmp + pos) != elem) + scrattr(id, 0xbe); + + scrprintf(id, "%s", tempstring); + } + + } + + tmp++; + } + redraw = 0; + } + + displayscreen(id); + updateptc(); + + while (last_tick == timer_tick) + SDL_Delay(1); + + last_tick = timer_tick; + + while (getkeys()) + { + redraw = 1; + + if (lastkeysym >= 0) + { + if (lastkeysym == SDLK_ESCAPE) + esc = 1; + else if ((lastkeysym == SDLK_x) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-x + else if ((lastkeysym == SDLK_F4) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-f4 + + else if (lastkeysym == SDLK_DOWN) + { + if (elem < elems) + { + tmp = elem + 1; + + while ((tmp < elems) && (opts[tmp].id == 0)) + tmp++; + + if (tmp < elems) + { + elem = tmp; + } + } + } + + else if (lastkeysym == SDLK_UP) + { + if (elem < elems) + { + tmp = elem - 1; + + while ((tmp >= 0) && (opts[tmp].id == 0)) + tmp--; + + if (tmp >= 0) + { + elem = tmp; + } + } + } + + else if (lastkeysym == SDLK_HOME) + { + elem = 0; + } + + else if (lastkeysym == SDLK_END) + { + elem = elems-1; + } + + else if (lastkeysym == SDLK_PAGEUP) + { + tmp = elem-1; + while (tmp>0) + { + if (opts[tmp-1].id) + tmp--; + else + break; + } + + while ((tmp>0) && !opts[tmp].id) + tmp --; + + if (tmp<0) tmp = 0; + + elem = tmp; + } + + else if (lastkeysym == SDLK_PAGEDOWN) + { + tmp = elem; + while ((tmp=elems) + tmp = elems - 1; + + elem = tmp; + } + + else if (selected >= 0) + { + +// scrprintf(id,"key: %d keysym: %d\n", lastkey, lastkeysym); +// displayscreen(id); +// updateptc(); +// SDL_Delay(1000); + if (opts[selected].set_handler) + esc = opts[selected].set_handler(opts[selected].id, lastkey, lastkeysym); + + selected = -1; + + } + + } + + if ((lastkey > 0) && !quit && !esc) + { + + if (selected >= 0) + { + if (opts[selected].set_handler) + esc = opts[selected].set_handler(opts[selected].id, lastkey, lastkeysym); + } + } + + if (lastkey == -2) + quit = 1; + } + } + return quit; +} + +void saveoptions() +{ + int qi; + char tempstring[256]; + + FILE *f; + + scrwindow(SCR_ID_OPTIONS, 20, (SCR_ROWS/2)-2, 40, 5, 0x7c, "Save settings"); + scrattr(SCR_ID_OPTIONS, 0x7b); + + if ((f = fopen("emu65el02.ini", "wb")) != NULL) + { + qi = 0; + while (option_menu[qi].id>=0) + { + if (option_menu[qi].cfg_name) + { + if (option_menu[qi].print_handler) + { + option_menu[qi].print_handler(option_menu[qi].id, tempstring); + fprintf(f,"%s=%s\n",option_menu[qi].cfg_name,tempstring); + } + } + qi ++; + } + + for (qi = 0; qi<256; qi++) + { + if (peripherals[qi]) + { + fprintf(f,"dev_%d=%d\n",qi,peripherals[qi]); + } + } + fclose(f); + + scrxy(SCR_ID_OPTIONS, 27, (SCR_ROWS/2)); + scrprintf(SCR_ID_OPTIONS, "Settings saved sucessfully"); + qi = 60; + } + else + { + scrxy(SCR_ID_OPTIONS, 24, (SCR_ROWS/2)); + scrprintf(SCR_ID_OPTIONS, "File write error (emu65el02.ini)"); + qi = 60000; + } + + displayscreen(SCR_ID_OPTIONS); + + while (!getkeys() && (qi-- > 0)) + { + updateptc(); + SDL_Delay(25); + }; + +} + +void readoptions() +{ + FILE *f; + char line[256]; + char label[256]; + char *ptr; + int tmp; + + if ((f = fopen("emu65el02.ini", "rb")) != NULL) + { + while (!feof(f)) + { + fgets(line, sizeof(line), f); + cleanstring(line); + if (*line) + { + ptr = getlabelfromstr(label,line); +// printf("%s = %s\n",label, ptr); + + if (!strcasecmp(label,"default_monitor_id")) + cpu.byte1 = atoi(ptr); + + if (!strcasecmp(label,"default_drive_id")) + cpu.byte0 = atoi(ptr); + + if (!strcasecmp(label,"cpu_speed")) + { + if (!strcasecmp(ptr,"1x")) + cpu.cycles_per_tick = 1000; + if (!strcasecmp(ptr,"2x")) + cpu.cycles_per_tick = 2000; + if (!strcasecmp(ptr,"5x")) + cpu.cycles_per_tick = 5000; + if (!strcasecmp(ptr,"10x")) + cpu.cycles_per_tick = 10000; + if (!strcasecmp(ptr,"100x")) + cpu.cycles_per_tick = 100000; + } + + if (!strcasecmp(label,"mmu_type")) + { + if (!strcasecmp(ptr,"bigfoot")) + cpu.mmu_type = 1; + } + + if (!strcasecmp(label,"io_penality")) + { + if (!strcasecmp(ptr,"off")) + cpu.no_io_penality = 1; + } + + if (!strcasecmp(label,"drive_boost")) + { + if (!strcasecmp(ptr,"on")) + drive_io_penality = 0; + } + + if (!strcasecmp(label,"spbugfix")) + { + if (!strcasecmp(ptr,"enabled")) + nospbug = 1; + } + + if (!strcasecmp(label,"memory_size")) + { + tmp = (atoi(ptr) << 10) & 0x1e000; + if (tmp > 0x10000) + tmp = 0x10000; + if (tmp < 0x2000) + tmp = 0x2000; + memory_max = tmp; + } + + if (!strncasecmp(label,"dev_",4)) + { + tmp = atoi(label+4); + peripherals[tmp & 0xff] = atoi(ptr); + +// printf("%d = %d\n",tmp, atoi(ptr)); + } + } + } + } +} + + +int options() +{ + return options_handler(SCR_ID_OPTIONS, option_menu, "Options",0); + +} + +int optperipherals() +{ + return options_handler(SCR_ID_PERIPHERALS, peripherals_menu, "Peripherals",0); +} + +int help() +{ + int esc = 0, quit = 0, last_tick = -1; + char hdr[] = "Help"; + + openscreen(SCR_ID_HELP); + scrblink(SCR_ID_HELP, 0); + drawstring(0, C_SIZEY-1, "\r ESC - Back", 0x0f, 0x09, rom_charset); + + scrclr(SCR_ID_HELP); + scrattr(SCR_ID_HELP, 0x7b); + scrprintf(SCR_ID_HELP, "%*s", SCR_COLS, ""); + scrxy(SCR_ID_HELP, (80-strlen(hdr))/2, 0); + scrprintf(SCR_ID_HELP, "%s", hdr); + scrattr(SCR_ID_HELP, 0xbe); + scrxy(SCR_ID_HELP,0,2); + scrprintf(SCR_ID_HELP,"Help isn't finished yet.\n\nPress ESC to leave this screen.\n"); + + while (!quit && !esc) + { + displayscreen(SCR_ID_HELP); + updateptc(); + + while (last_tick == timer_tick) + SDL_Delay(1); + + last_tick = timer_tick; + + while (getkeys()) + { + if (lastkeysym >= 0) + { + if (lastkeysym == SDLK_ESCAPE) + esc = 1; + else if ((lastkeysym == SDLK_x) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-x + else if ((lastkeysym == SDLK_F4) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-f4 + + else if (lastkeysym == SDLK_DOWN) + { + } + + else if (lastkeysym == SDLK_UP) + { + } + + } + + if ((lastkey > 0) && !quit && !esc) + { + } + + if (lastkey == -2) + quit = 1; + } + } + + return quit; +} + +int optiox(int iox) +{ + char hdr[] = "IO extenders"; + + int quit = 0, esc = 0; + + int top_id = 0, row = 0, bit = 0; + + int ref[256]; + int maxref = 0; + + int redraw = 1, last_tick = -1; + int qi, tmp, tmprow, selected; + + int bit_colors[16] = { 0x10, 0x80, 0x1010, 0xe0, + 0x70, 0xd0, 0x1020, 0xc0, + 0xf0, 0x30, 0x40, 0x60, + 0x90, 0x50, 0x2f, 0x0f }; + + char *str_colors[16] = { + "White", + "Orange", + "Magenta", + "Light blue", + "Yellow", + "Lime", + "Pink", + "Gray", + "Light gray", + "Cyan", + "Purple", + "Blue", + "Brown", + "Green", + "Red", + "Black" }; + + char tempstring[256]; + +// 0 - White 4 - Yellow 8 - Light Gray 12 - Brown +// 1 - Orange 5 - Lime 9 - Cyan 13 - Green +// 2 - Magenta 6 - Pink 10 - Purple 14 - Red +// 3 - Light blue 7 - Gray 11 - Blue 15 - Black + + openscreen(SCR_ID_IOX); + scrblink(SCR_ID_IOX, 0); + drawstring(0, C_SIZEY-1, "\r Up/Down/Left/Right - Move Space - Set/unset ESC - Back", 0x0f, 0x09, rom_charset); + + if (iox < 0) + iox = last_iox; + + for (qi = 0; qi<256; qi++) + { + if (peripherals[qi] == 4) + ref[maxref++] = qi; + } + + if (iox >= 0) + { + tmp = 0; + while ((tmp0)) + { + if (maxref >= 4) + { + if (tmp < maxref - 3) + { + top_id = tmp - 1; + row = 1; + } + else + { + top_id = maxref - 4; + row = tmp - top_id; + } + } + else + { + row = tmp; + } + } + + } + + while (!quit && !esc) + { + if (redraw) + { + selected = -1; + + scrclr(SCR_ID_IOX); + scrattr(SCR_ID_IOX, 0x7b); + scrprintf(SCR_ID_IOX, "%*s", SCR_COLS, ""); + scrxy(SCR_ID_IOX, (80-strlen(hdr))/2, 0); + scrprintf(SCR_ID_IOX, "%s", hdr); + + for (qi = 0; qi < 16; qi++) + { + scrattr(SCR_ID_IOX, bit_colors[qi]); + + scrxy(SCR_ID_IOX, 1 + (qi >> 2) * 20, 45 + (qi & 3)); + scrprintf(SCR_ID_IOX," %x: %13s ", qi, str_colors[qi]); + + } + + if (maxref) + { + + for (qi = 0; qi < 16; qi ++) + { + scrattr(SCR_ID_IOX, bit_colors[15-qi]); + scrxy(SCR_ID_IOX, 18 + qi * 3, 6); + scrprintf(SCR_ID_IOX, " %x ",15-qi); + } + + tmp = top_id; tmprow = 0; + while ((tmp < maxref) && (tmprow<4)) + { + if (tmprow == row) + { + selected = tmp; + scrattr(SCR_ID_IOX, 0x1007); + } + else + scrattr(SCR_ID_IOX, 0xb7); + + scrxy(SCR_ID_IOX, 0, 8 + tmprow * 8); + scrprintf(SCR_ID_IOX, "%*s", SCR_COLS, ""); + scrprintf(SCR_ID_IOX, "%*s", SCR_COLS, ""); + scrprintf(SCR_ID_IOX, "%*s", SCR_COLS, ""); + scrprintf(SCR_ID_IOX, "%*s", SCR_COLS, ""); + scrprintf(SCR_ID_IOX, "%*s", SCR_COLS, ""); + + scrxy(SCR_ID_IOX, 3, 10 + tmprow * 8); + sprintf(tempstring,"#%d",ref[tmp]); + scrprintf(SCR_ID_IOX,"%4s",tempstring); + + scrxy(SCR_ID_IOX, 10, 9 + tmprow * 8); + scrprintf(SCR_ID_IOX,"input:"); + scrxy(SCR_ID_IOX, 9, 11 + tmprow * 8); + scrprintf(SCR_ID_IOX,"output:"); + + scrxy(SCR_ID_IOX, 69, 9 + tmprow * 8); + scrprintf(SCR_ID_IOX,"= $%04X",ioextender[ref[tmp]].input & 0xffff); + scrxy(SCR_ID_IOX, 69, 11 + tmprow * 8); + scrprintf(SCR_ID_IOX,"= $%04X",ioextender[ref[tmp]].output & 0xffff); + + for (qi = 0; qi < 16; qi ++) + { + + if (tmprow == row) + { + if (bit == qi) + scrattr(SCR_ID_IOX, 0xbe); + else + scrattr(SCR_ID_IOX, 0x1007); + } + else + scrattr(SCR_ID_IOX, 0xb7); + + + scrxy(SCR_ID_IOX, 18 + qi * 3, 9 + tmprow * 8); + if ( (ioextender[ref[tmp]].input >> (15 - qi)) & 1 ) + scrprintf(SCR_ID_IOX," X "); + else + scrprintf(SCR_ID_IOX," _ "); + + if (tmprow == row) + scrattr(SCR_ID_IOX, 0x1007); + else + scrattr(SCR_ID_IOX, 0xb7); + + scrxy(SCR_ID_IOX, 18 + qi * 3, 11 + tmprow * 8); + if ( (ioextender[ref[tmp]].output >> (15 - qi)) & 1 ) + scrprintf(SCR_ID_IOX," X "); + else + scrprintf(SCR_ID_IOX," _ "); + + + scrattr(SCR_ID_IOX, bit_colors[15-qi]); + scrxy(SCR_ID_IOX, 18 + qi * 3, 14 + tmprow * 8); + scrprintf(SCR_ID_IOX, " %x ",15-qi); + } + + tmp++; + tmprow++; + } + + } + else + { + scrattr(SCR_ID_IOX, 0xb7); + scrxy(SCR_ID_IOX, 30,22); + scrprintf(SCR_ID_IOX, "No IO extender configured."); + } + + redraw = 0; + } + + displayscreen(SCR_ID_IOX); + updateptc(); + + while (last_tick == timer_tick) + SDL_Delay(1); + + last_tick = timer_tick; + + while (getkeys()) + { + redraw = 1; + + if (lastkeysym >= 0) + { + if (lastkeysym == SDLK_ESCAPE) + esc = 1; + else if ((lastkeysym == SDLK_x) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-x + else if ((lastkeysym == SDLK_F4) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-f4 + + else if (lastkeysym == SDLK_DOWN) + { + if ( (top_id + row) < (maxref - 1) ) + { + if (row < 3) + row ++; + else + top_id++; + } + } + + else if (lastkeysym == SDLK_UP) + { + if (row > 0) + row --; + else if (top_id > 0) + top_id --; + } + + else if (lastkeysym == SDLK_LEFT) + { + if (bit > 0) + bit --; + } + + else if (lastkeysym == SDLK_RIGHT) + { + if (bit < 15) + bit ++; + } + + } + + if ((lastkey > 0) && !quit && !esc) + { + if ((lastkey == 0x20) && (selected >= 0)) + { + ioextender[ref[selected]].input ^= (1 << (15 - bit)); + } + } + + if (lastkey == -2) + quit = 1; + } + } + + if ((selected >= 0) && (selected < maxref)) + last_iox = ref[selected]; + + return quit; +} + +int optdrive(int id) +{ + int quit = 0, esc = 0, last_tick = -1, pos = 0; + int redraw = 1; + char tempstring[256]; + + + openscreen(SCR_ID_DRIVE); + + while (!quit && !esc) + { + if (redraw) + { + scrclone(SCR_ID_DRIVE, SCR_ID_PERIPHERALS); + sprintf(tempstring,"Drive id %d setup",id); + scrwindow(SCR_ID_DRIVE, 15, 22, 50, 7, 0x100e, tempstring); + scrattr(SCR_ID_DRIVE, 0x100e); + + scrxy(SCR_ID_DRIVE,17,24); + scrprintf(SCR_ID_DRIVE, "Image type: "); + if (pos == 0) + scrattr(SCR_ID_DRIVE, 0x97); + + else + scrattr(SCR_ID_DRIVE, 0x100d); + + if (!drives[id].name) + { + scrprintf(SCR_ID_DRIVE, "no disk"); + scrattr(SCR_ID_DRIVE, 0x100e); + scrxy(SCR_ID_DRIVE,17,26); + scrprintf(SCR_ID_DRIVE, "Image name: "); + } + + else if (!drives[id].type) + { + if (strlen(drives[id].name) > 30 ) + sprintf(tempstring, "...%s -->", drives[id].name + strlen(drives[id].name) - 27); + else + sprintf(tempstring, "%s -->", drives[id].name); + + scrprintf(SCR_ID_DRIVE, "user"); + + scrattr(SCR_ID_DRIVE, 0x100e); + scrxy(SCR_ID_DRIVE,17,26); + scrprintf(SCR_ID_DRIVE, "Image name: "); + scrattr(SCR_ID_DRIVE, 0xd10); + if (pos == 1) + scrattr(SCR_ID_DRIVE, 0x97); + else + scrattr(SCR_ID_DRIVE, 0x100d); + scrprintf(SCR_ID_DRIVE, "%s", tempstring); + + + } + else if (drives[id].type == 1) + { + scrprintf(SCR_ID_DRIVE, "built-in"); + + scrattr(SCR_ID_DRIVE, 0x100e); + scrxy(SCR_ID_DRIVE,17,26); + scrprintf(SCR_ID_DRIVE, "Attached image: "); + scrattr(SCR_ID_DRIVE, 0x100d); + scrprintf(SCR_ID_DRIVE, "MineOS (System)"); + } + + redraw = 0; + } + + displayscreen(SCR_ID_DRIVE); + updateptc(); + + while (last_tick == timer_tick) + SDL_Delay(1); + + last_tick = timer_tick; + + while (getkeys()) + { + redraw = 1; + + if (lastkeysym >= 0) + { + if (lastkeysym == SDLK_ESCAPE) + esc = 1; + else if ((lastkeysym == SDLK_x) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-x + else if ((lastkeysym == SDLK_F4) && (lastkeymod & KMOD_ALT)) + quit = 1; // alt-f4 + + else if (lastkeysym == SDLK_DOWN) + { + } + + else if (lastkeysym == SDLK_UP) + { + } + + } + + if ((lastkey > 0) && !quit && !esc) + { + } + + if (lastkey == -2) + quit = 1; + } + } + + return quit; +} diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..8ec1783 --- /dev/null +++ b/src/screen.c @@ -0,0 +1,293 @@ +#include +#include +#include +#include + +#include "memory/memory.h" +#include "video/gbuffer.h" +#include "screen.h" + +void initscreen() +{ + memset(&screens,0x00,sizeof(screens)); + memset(&screencache,0x00,sizeof(screenstruct)); + last_screen_type = 0; +} + +void scrattrfill(int scr, unsigned short attr) +{ + int qi, qj; + + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + for (qi = 0; qiattributes.rowcol[qi][qj] = attr; + } + } +} + + +void scrclr(int scr) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + memset(&screens[scr]->chars, 0x20, SCR_SIZE); + scrattrfill(scr, 0xbd); + screens[scr]->cx = 0; + screens[scr]->cy = 0; + screens[scr]->attr = 0xbd; + } + } +} + +screenstruct *openscreen(int scr) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] == NULL) + { + screens[scr] = malloc(sizeof(screenstruct)); + memset(screens[scr],0x00,sizeof(screenstruct)); + memset(&screens[scr]->chars, 0x20, SCR_SIZE); + scrattrfill(scr, 0xbd); + screens[scr]->blink = 2; + screens[scr]->attr = 0xbd; + + if (scr < 0x100) + screens[scr]->type = 0; + else + screens[scr]->type = 1; + } + + return(screens[scr]); + } + + else + return NULL; +} + +void closescreen(int scr) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + free(screens[scr]); + screens[scr] = NULL; + } + } +} + +void shutdownscreen() +{ + int qi; + for (qi = 0; qi < MAX_SCREENS; qi++) + closescreen(qi); +} + +void displayscreen(int scr) +{ + + int qi, qj; + unsigned char ch; + unsigned short attr; + int forceupdate = !(timer_tick % 20); + + if ((scr <0) && (scr >= MAX_SCREENS)) + return; + + if (screens[scr] == NULL) + return; + + if (last_screen_type != screens[scr]->type) + { + last_screen_type = screens[scr]->type; + forceupdate = 1; + } + + for (qi = 0; qi < SCR_ROWS; qi++) + { + for (qj = 0; qj < SCR_COLS; qj++) + { + ch = screens[scr]->chars.rowcol[qi][qj]; + attr = screens[scr]->attributes.rowcol[qi][qj]; + if ((screens[scr]->cx == qj) && (screens[scr]->cy == qi)) + { + switch(screens[scr]->blink) + { + case 0x01: + ch ^= 0x80; + break; + case 0x02: + if ( ((timer_tick >> 2) & 1) == 0 ) + ch ^= 0x80; + break; + } + } + + if ( (ch != screencache.chars.rowcol[qi][qj]) || (attr != screencache.attributes.rowcol[qi][qj]) || forceupdate) + { + if (screens[scr]->type == 1) + { + drawchar(qj + 1, qi + 2, ch, (attr & 0x0f) | ((attr >> 4) & 0xf0), ((attr >> 4) & 0x0f) | ((attr >> 8) & 0xf0), rom_charset); + } + else + { + drawchar(qj + 1, qi + 2, ch, 0x0d, 0x10, rom_charset); + } + + screencache.chars.rowcol[qi][qj] = ch; + screencache.attributes.rowcol[qi][qj] = attr; + } + + } + } + + +} + +void scrxy(int scr, int x, int y) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + screens[scr]->cx = x; + screens[scr]->cy = y; + } + } +} + +void scrattr(int scr, unsigned short attr) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + screens[scr]->attr = attr; + } + } +} + +void scrblink(int scr, unsigned char blink) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + screens[scr]->blink = blink; + } + } +} + +void scrtype(int scr, unsigned char type) +{ + if ((scr >=0) && (scr < MAX_SCREENS)) + { + if (screens[scr] != NULL) + { + screens[scr]->type = type; + } + } +} + +void scrprintf(int scr, const char *fmt, ...) +{ + unsigned char buf[1024]; + unsigned char *ptr = buf; + + va_list va; + int len; + + va_start(va, fmt); + vsnprintf(buf, sizeof(buf), fmt, va); + va_end(va); + + if ((scr <0) && (scr >= MAX_SCREENS)) + return; + + if (screens[scr] == NULL) + return; + + while (*ptr) + { + if (*ptr>=0x20) + { + screens[scr]->attributes.rowcol[screens[scr]->cy][screens[scr]->cx] = screens[scr]->attr; + screens[scr]->chars.rowcol[screens[scr]->cy][screens[scr]->cx++] = *ptr; + } + else + { + if (*ptr == '\n') + { + screens[scr]->cy++; + screens[scr]->cx=0; + } + if (*ptr == '\t') + { + screens[scr]->cx = (screens[scr]->cx & 0xf8) + 8; + } + + if (*ptr == 0x08) + { + if (screens[scr]->cx>0) + screens[scr]->chars.linear[screens[scr]->cy*SCR_COLS + (--screens[scr]->cx)]=0x20; + } + } + + if (screens[scr]->cx>=SCR_COLS) + { + screens[scr]->cy++; + screens[scr]->cx = 0; + } + + if (screens[scr]->cy>=SCR_ROWS) + { + memcpy(screens[scr]->chars.linear,screens[scr]->chars.linear + SCR_COLS,sizeof(screens[scr]->chars.linear)-SCR_COLS); + memset(screens[scr]->chars.linear + (SCR_ROWS-1)*SCR_COLS,0x20,SCR_COLS); + screens[scr]->cy=SCR_ROWS-1; + } + + *ptr++; + } +} + +void scrwindow(int scr, int x, int y, int sx, int sy, unsigned short attr, char *hdr) +{ + int qi; + + scrattr(scr, (attr >> 4) | (attr << 4)); + + for (qi=y; qi=0) && (scr < MAX_SCREENS) && (src >=0) && (src < MAX_SCREENS)) + { + if ((screens[scr] != NULL) && (screens[scr] != NULL)) + { + memcpy(screens[scr],screens[src],sizeof(screenstruct)); + } + } +} \ No newline at end of file diff --git a/src/video/gbuffer.c b/src/video/gbuffer.c new file mode 100644 index 0000000..f1d5707 --- /dev/null +++ b/src/video/gbuffer.c @@ -0,0 +1,237 @@ +//--------------------------------------------------------------------------- +#include +#include "video/colors.h" +#include "video/gbuffer.h" +//--------------------------------------------------------------------------- + +static SDL_Surface *screen = NULL; + +typedef struct { + int lastkey; + int lastkeysym; + int lastkeymod; +} keyb; + +static keyb keys[100]; +static int keybufferlen; + +int timer_tick = 0; + +static Uint32 timer_handler(Uint32 interval, void *param) +{ + timer_tick ++; + return(interval); +} + +int startptc(char *label) +{ + SDL_Color palette[256]; + int qi; + + lastkey = -1; + lastkeysym = -1; + lastkeymod = -1; + + keybufferlen = 0; + + if ( (screen = SDL_SetVideoMode(WINSIZEX,WINSIZEY,8,SDL_SWSURFACE)) == NULL) + { + return 0; + } + + memset(&palette,0x00,sizeof(palette)); + for (qi = 0; qi < sizeof(palette)/sizeof(unsigned int); qi++) + { + palette[qi].r = (colors[qi] >> 16) & 0xff; + palette[qi].g = (colors[qi] >> 8) & 0xff; + palette[qi].b = colors[qi] & 0xff; + } + + SDL_SetColors(screen, palette, 0, 256); + + if ( SDL_LockSurface(screen) < 0 ) + { + return 0; + } + + SDL_WM_SetCaption(label, label); + + SDL_AddTimer(1000/20, timer_handler, NULL); + + return 1; +} + +//--------------------------------------------------------------------------- +int getkeys() +{ +int i; + + if (keybufferlen > 0) + { + lastkey = keys[0].lastkey; + lastkeysym = keys[0].lastkeysym; + lastkeymod = keys[0].lastkeymod; + + for (i=1; i= 128)) + keys[keybufferlen].lastkey = 0; + + keybufferlen++; + } + + break; + + case SDL_KEYUP: + if (keybufferlen < 100) + { + keys[keybufferlen].lastkey = -1; + keys[keybufferlen].lastkeysym = -1; + keys[keybufferlen++].lastkeymod = -1; + } + break; + + case SDL_QUIT: + keys[0].lastkey = -2; + keys[0].lastkeysym = -1; + keybufferlen = 1; + break; + default: + break; + } + + count ++; + } + +} +void updateptc() +{ + SDL_UnlockSurface(screen); + SDL_UpdateRect(screen, 0, 0, 0, 0); + SDL_LockSurface(screen); + events(); + +} + +//--------------------------------------------------------------------------- +void endptc() +{ + SDL_UnlockSurface(screen); + SDL_FreeSurface(screen); +} + +//----------------------------------------------------------------------------- +void drawchar(int cx, int cy, unsigned char ch, unsigned char fgcolor, unsigned char bgcolor, unsigned char *charset) +{ + int charsetstart, qi, qj; + int mempos; + char tempreg; + + char *pixels = screen->pixels; + + charsetstart = (ch << 3); + + cy = cy << 3; + cx = cx << 3; + for (qi = cy; qi < cy + 8; qi++) + { + tempreg = charset[charsetstart++]; + mempos = (2 + qi) * screen->pitch + cx + 2; + + if ((tempreg & 0x80) == 0x80) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x40) == 0x40) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x20) == 0x20) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x10) == 0x10) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x08) == 0x08) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x04) == 0x04) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x02) == 0x02) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + if ((tempreg & 0x01) == 0x01) + pixels[mempos++] = fgcolor; + else + pixels[mempos++] = bgcolor; + + } +} + +//--------------------------------------------------------------------------- +void drawstring(int cx, int cy, unsigned char *str, unsigned char fgcolor, unsigned char bgcolor, void *charset) +{ + int qi; + + while (*str != 0) + { + if (*str == '\r') + { + for (qi = cx; qi