7 ms·
Intel 8080 emulator. 19th IOCCC. Best of Show
- nsxwolf 3y agoIs there an ELI5 for this? How could something so small possibly be an 8080 emulator?
- bombcar 3y agoThe 8080 is a simple processor, the "how to program" manual is only 60 pages. Most of the instructions are changing registers in various ways, which is pretty simple. The Appendix A has all of them: https://altairclone.com/downloads/manuals/8080%20Programmers%20Manual.pdf https://altairclone.com/downloads/manuals/8080%20Programmers...
- tromp 3y agoI am more amazed you can fit a (pretty large subset of) Haskell compiler/runtime in about twice the size [1]. [1] https://www.ioccc.org/2019/lynn/hint.html https://www.ioccc.org/2019/lynn/hint.html
- anthk 3y agoWell, an a complete lisp system on that size, for sure. And forth environment.
- ngcc_hk 3y agoExample? I meant under 8080. Seems to have sector size using x86?
- anthk 3y agoThe former meant under x86, and that's easy even for IOCCC.With awk you can write an RPN calculator in 10 lines or such...
- anthk 3y agoI found a Forth for x86 under the IOCCC contest of 1992: the Buzzward.2 entry. https://www.ioccc.org/1992/1992.tar.bz2 https://www.ioccc.org/1992/1992.tar.bz2 You need to edit the CFLAGS (or just comment that line), and by using gcc or even tcc will work fine.
- none_to_remain 3y agoI went too far and ran into the printed hexadecimal-decimal lookup table for every number from 0x0-0xFFF
- dekhn 3y agoah yes, I had that poster on my wall as a kid... https://twitter.com/JBrooksBSI/status/952291667041599488/photo/1 https://twitter.com/JBrooksBSI/status/952291667041599488/pho...
- bombcar 3y agoNow I'm having fond memories of discovering the IBM box drawing characters above 128 as a kid, and doing fancy text files.
- belter 3y agoIt's the Toledo family. All is possible. https://news.ycombinator.com/item?id=28337064 https://news.ycombinator.com/item?id=28337064
- msla 3y agoGiven the number of lies on the company's website, I'm not inclined to believe them about other things.
- anthk 3y agoThe articles on the browser tech are horribily outdated, and ditto with TLS libraries. But if they used something like mbedtls/bearssl and Gemini/Gopher, they would be still useful.
- philomath_mn 3y agoWow, that sent me down a rabbit hole -- but this line from the homepage makes it sound like he is _not_ part of that family? > If you're looking for information about the Mexican scientist Oscar Toledo Esteva, then please go to the History page of the Familia Toledo organization site. https://nanochess.org/index.html https://nanochess.org/index.html
- emi2k01 3y agoI believe they are father and son. The `Books` section on the Toledo family website links to books written by Oscar Toledo G.
- philomath_mn 3y agoGood catch -- those same books show up on the nanochess site: https://nanochess.org/author.html https://nanochess.org/author.html Odd that he doesn't mention the "scientist" people may be looking for is his father, but everything else lines up.
- kqr2 3y ago
- slily 3y agoThe 8080 instruction set opcodes have logical bit patterns, so you can identify the operation and operands through bit masking instead of requiring a huge LUT. Beyond that you can simplify a lot by sacrificing timing accuracy.
- zabzonk 3y agoyou can also write one using a 256-byte switch, which ain't so big. i wrote an 8080 emulator in fortran77 on a dec10 that way, back in the 1980s. but of course size wasn't an issue. it did prove to be quite portable - to vax and ibm vm/cms. we used it for teaching assembler programming.
- RetroTechie 3y agoThe 8080 has ~5k transistors. There's only so much complexity one can build with those.
- xcv123 3y agoAfter simplifying and reducing the code as far as possible, it is rewritten in a compressed format using macros and without whitespace. Look at the #define statements.
- nanochess 3y agoThe simplest emulator in the world would be like this one: unsigned char memory[65536]; int reg[8]; int main(void) { int pc = 0; /* In this point you read something into memory */ while (1) { instruction = memory[pc]; if (instruction == 0x76) break; /* HLT */ pc = (pc + 1) & 0xffff; if ((instruction & 0xc0) == 0x40) /* Handle MOV r,r (opcodes 0x40-0x7f) */ reg[(instruction >> 3) & 7] = reg[instruction & 7]; } return 0; } What it does? It simply reads each instruction from memory (PC is the Program Counter), and increments PC continuously limiting it to 16-bit. It does a comparison for each possible instruction, for this example I only handled the most basic one of 8080 (MOV r,r) and HLT, but this is already 64 cases of the 256 possible! Then I added iteratively chunks of opcodes to emulate and used language C macros to reduce the code size. For example, there is #define d(e) to join two 8-bit registers into a 16-bit value, and #define Q to read the accumulator. In the end, to stay inside the size limit of the IOCCC, I removed the tree of 'if' statements and replaced it with a tree of trinary operators ?: (a way of doing 'if' inside an expression) and this is what the macros C and S does.
- tromp 3y agoSadly, the International Obfuscated C Code Contest has not been held in the past 3 years, the last one being the 27th IOCCC from 2020 [1]. Looking forward to seeing more editions in the future, and submitting another entry myself... [1] https://www.ioccc.org/years.html#2020 https://www.ioccc.org/years.html#2020
- howerj 3y agoI've been waiting for the competition to open up again, I think I have an entry good enough. There does appear to be some activity on their GitHub repo, but I have no idea when the next one will be. Does anyone here have any gossip about when the next one might be? Wild rumor would also suffice.
- hfuaiobfa 3y agoThey seem to be re-organizing the website structure [1] as well as updating the submitting system [2], and lately they were making some progress [3], but still need a lot of formatting work. [1] https://github.com/ioccc-src/temp-test-ioccc https://github.com/ioccc-src/temp-test-ioccc [2] https://github.com/ioccc-src/mkiocccentry https://github.com/ioccc-src/mkiocccentry [3] https://fosstodon.org/@ioccc/112023138011006567 https://fosstodon.org/@ioccc/112023138011006567 There are currently only two active maintainers. I guess any help is welcome.
- K0balt 3y agoSeems like they are stretched a bit thin, and no doubt this is a hobby project. This is a great steelman for where dogfooding does not apply - imagine if their website was actually an obfuscated C webserver with the content imbedded in it, and therefore impossible to update lol.
- knodi123 3y agoanother casualty of the covid era, I assume /s
- Retr0id 3y ago
- dormento 3y ago> I intended to make it simple to understand, it uses only four C keywords. Fantastic
- wzdd 3y agoRelated, 8086tiny, a 2013 IOCCC winner. About twice as much source code, and if not cheating then certainly leaning heavily on the rules, but very impressive as it's a full x86 emulator with graphics and several peripherals. Original entry: https://www.ioccc.org/years.html#2013_cable3 https://www.ioccc.org/years.html#2013_cable3 "Deobfuscated": https://github.com/adriancable/8086tiny https://github.com/adriancable/8086tiny (Not mine, just a fan)
- rahkiin 3y agoFrom the description, one small part of the code: --64[T=1[O=32[L=(X=*Y&7)&1,o=X/2&1,l]=0,t=(c=y)&7,a=c/8&7,Y]>>6,g=~-T?y:(n)y,d=BX=y,l] The difference between bf and c sometimes is small
- lifthrasiir 3y agoIt is in fact quite reasonable if you know a bit of C obfuscation and some expectation about 8086 interpreters. First, indentations: --64[ T=1[ O=32[ L=(X=*Y&7)&1, o=X/2&1, l ]=0, t=(c=y)&7, a=c/8&7, Y ]>>6, g=~-T?y:(n)y, d=BX=y, l ] `a, b` will return `b` but evaluate `a` as a side effect, so anything preceding `,` can be (recursively) pulled out. L=(X=*Y&7)&1, o=X/2&1, O=32[l]=0, t=(c=y)&7, a=c/8&7, T=1[Y]>>6, g=~-T?y:(n)y, d=BX=y, --64[l] `a[b]` is semantically equivalent to `*(a + b)`, so it is unexpectedly commutative. Let's swap them all and add some spacing. Ah, also some assignment expressions have been reused as a part of other expressions, which I will also pull out: X = *Y & 7, L = X & 1, o = X / 2 & 1, O = l[32] = 0, c = y, t = c & 7, a = c / 8 & 7, T = Y[1] >> 6, g = ~-T ? y : (n) y, d = BX = y, --l[64] Now it should be much more clear that a large chunk of this code is instruction decoding. At this point we need to expand macros to make more sense out of it: #define Z short #define a(_)*(_*)& #define y a(Z)Y[++O] #define n char It would need more reading to determine the exact meaning of `Y`, but given that its type is `unsigned char*`, it should be some sort of pointer, most likely the instruction pointer. The macro `y`, which expands to `*(short*)&Y[++O]`, increases `O` so it looks like reading from IP+0, IP+1, ... while not actually advancing the IP. So the mysterious code can be now mostly decoded: X = *Y & 7, // [IP+0] = ?????XXX L = X & 1, // = ???????L o = X / 2 & 1, // = ??????o? O = l[32] = 0, // Reset `O` for further uses of `y` c = y, // [IP+1] = yyyyyyyy t = c & 7, // = ?????ttt a = c / 8 & 7, // = ??aaa??? T = Y[1] >> 6, // = TT?????? g = ~-T ? y : (char) y, // Read [IP+2] and do something d = BX = Y[++O], // [IP+3] = dddddddd --l[64] [IP+1] surely looks like the ModR/M byte, so you can guess that `g` is a displacement even if you don't know what the heck is `~-T` (equals to `T - 1` in twos' complement). [IP+0] is too generic to pick the exact instruction, but my guess is that this code is shared for a lot of similar opcodes to save the code footprint.
- anthk 3y agoBTW, CPM 2.2 doesn't run on that emulator in my machine (intel Atom, Linux, 32 bit, tried with gcc 8, clang 11, and tcc 0.29.7). Basic does.
- fernirello 3y agoSadly, same here: following the instrs works for Tiny Basic (which is quite basic!), but CP/M segfaults. Any idea to get past this?
- cowboylowrez 3y agochmod +w A B after the copy got me a bios prompt!
- anthk 3y agoThanks!!
- simlevesque 3y agoIt compiles on my machine but I can't run it, I always get a SIGSEGV. Same thing for the chess program. I ran both the original build command and the "And now it is 2024" one.
- skulk 3y agoFor the 8080 emulator, you need the c_basic.bin (renamed to just "C") and c_bios.bin to be in the same directory as the executable, as per the article. I tried this and it dumps me into a BASIC shell. So cool!
- verall 3y agoA somewhat related ask for help - I have seen a program, I think for IOCCC, where the code was aligned in 4 character columns that seemed to naturally fit the code, so it would have code arranged like: for( long i=0; i<n; i++) {int a=1, b=2, c=3, d=4; for the whole program. I lost it though and have been completely unable to find it, despite searching very hard. Has anyone seen something like this before? I would be forever grateful for any pointer towards it.
- omoikane 3y agoWas it one of these? https://www.ioccc.org/years.html#1995_heathbar https://www.ioccc.org/years.html#1995_heathbar https://www.ioccc.org/years.html#2014_endoh1 https://www.ioccc.org/years.html#2014_endoh1 https://www.ioccc.org/years.html#2006_sloane https://www.ioccc.org/years.html#2006_sloane May be related, I have an index that lists winning entries with some form of ASCII art, one of those could be what you were looking for. https://docs.google.com/spreadsheets/d/e/2PACX-1vRg3T5z-QN66exVfyQZdLBPEEALRU3I5z4YkvtqyiohK8RjTZIRG18oz-BVPpU8T5aMq1lh7jLUpxL6/pubhtml https://docs.google.com/spreadsheets/d/e/2PACX-1vRg3T5z-QN66...
- bruce343434 3y agoWhat did it do?
- verall 3y agoIt was an interpreter for something. I don't remember what
- xuhu 3y agoIs there a competition where you win by showing something both compact and extraordinary but not obfuscated ? Like zlib compression in 100 lines or some song recognition using FFT in X lines, or a working ssh client in Y lines ?
- frakt0x90 3y agoDemoscene? Mostly geared towards graphics but that's one example.
- nneonneo 3y agoThis is generally called code golf, and there’s a whole forum for it: https://codegolf.stackexchange.com/ https://codegolf.stackexchange.com/ I think once you try to get something small enough the code will naturally tend towards obfuscation.
- boffinAudio 3y agoThere is the 10-line BASIC Coding competition, which is frankly AWESOME: https://gkanold.wixsite.com/homeputerium/copy-of-rules https://gkanold.wixsite.com/homeputerium/copy-of-rules Some of the winners of the last few years have been extraordinary - complete arcade games, with physics, in just 10 lines of BASIC. This competition definitely highlights the issue we have with software development, which is that we, as a species, don't generally get really good at it for decades...
- billforsternz 3y agoOne of my best hacks back in the day was an 8080 emulator, for the 8088/8086 back in the time when what you were really trying to do was run the 8080 code as fast as possible (because the first PCs were slow, and emulating 8080 code was much slower than running 8080 code on a native machine). Invariably at the time the 8080 emulators would have a dispatch loop, fetching the next opcode and dispatching through a jump table to some code to emulate each of the 256 opcodes. One problem with this was that you couldn't dispatch this way without altering the CPU flags, so you'd also have to save and restore those with LAHF/SAHF (fast) or PUSHF/POPF (slow). In general you'd need about 10 8086 instructions to emulate 1 8080 instruction, and in the early 1980s this meant your emulated CP/M program would run much slower than on your old CP/M computer. My emulator would emulate 1 8080 opcode with 4 8086 opcodes as follows; An 8080 instruction, say 0x94 = sub h would be emulated with code loaded at address 0x9494. That code would be; sub bh,dl ;bh = bh-dl, emulate h with bh, a with dl lodsb ;al = *si++, get next opcode, increment emulated pc mov ah,al ;eg 0x94 -> 0x9494 jmp ax ;jump to next instruction This is a classic example of trading space for time, your emulator is sparsely distributed through 64K of RAM. So you needed 128K to emulate your 64K 8080.
- djmips 3y agoHow would full translation work? The opcodes are close? Could you do a just in time version?
- aap_ 3y agoI think the 8086 was designed such that 8080 assembly code could be assembled as 8086 machine code. So I'd guess the instruction emulation would probably be reasonably efficient.
- billforsternz 3y agoYes, pretty close so full translation is easy if you have the source code. If not, emulation is the normal way. My emulator was faster than native 8080 code on everything but vanilla 8088 PCs, so it's more than sufficient. I address translation in depth in my Retro Sargon project, an exercise in getting a vintage Z80 (8080 superset) assembly language program working on modern PCs. https://github.com/billforsternz/retro-sargon https://github.com/billforsternz/retro-sargon See the "Yet More Details" section in the README.
- ngcc_hk 3y agoIs there a "Deobfuscated" code?
- ngcc_hk 3y agoNot running on macOS arm due to llvm I guess? Not sure how to use brew without touching the llvm or Xcode etc., I switch to lima (search it under this news site for more details). It works (after doing sudo ... build essentials etc.). For the BASIC, not sure how to quit the environment after learning it in 1979! Seems Ctrl-Z give you a seg-fault and it quit ... :-) But not sure where is the core-dump generated ;-p For the CPM, must do the chmod +w A B as said (BUT NOT chmod +w A then chmod +w B ?!!). Still cannot exit the CPM until I dir and find the program HALT.COM (wow .COM) and A>HALT ... all good. :-)