////////// // // Called to append the datum // ////// s32 iBuilder_append_label_datum(SBuilder* builder, s8* tcLabelText, SDatum* datum) { s32 lnStart; // Make sure our environment's sane if (builder && tcLabelText && datum && datum->_data && datum->length > 0) { // Note our size at the stat lnStart = builder->populatedLength; // Label iBuilder_appendData(builder, tcLabelText, (s32)strlen(tcLabelText)); // Equals iBuilder_appendData(builder, " = ", 3); // Text iBuilder_appendData(builder, datum->data_s8, datum->length); // CR/LF iBuilder_appendCrLf(builder); // Indicate how many bytes were written return(builder->populatedLength - lnStart); } else { // Failure return(0); } }
////////// // // Called to append a label and a logical value as "true" or "false", followed by CR/LF // "name = true[cr/lf]" // ////// s32 iBuilder_append_label_logical(SBuilder* builder, s8* tcLabelText, bool tlValue) { s32 lnStart; // Make sure our environment's sane if (builder && tcLabelText) { // Note our size at the stat lnStart = builder->populatedLength; // Label iBuilder_appendData(builder, tcLabelText, (s32)strlen(tcLabelText)); // Equals iBuilder_appendData(builder, " = ", 3); // True/false iBuilder_appendData(builder, ((tlValue) ? "true" : "false"), ((tlValue) ? 4 : 5)); // CR/LF iBuilder_appendCrLf(builder); // Indicate how many bytes were written return(builder->populatedLength - lnStart); } else { // Failure return(0); } }
////////// // // Called to append a label and a signed value, followed by CR/LF // "name = 12345[cr/lf]" // ////// s32 iBuilder_append_label_sptr(SBuilder* builder, s8* tcLabelText, sptr sdata) { s32 lnStart; s8 buffer[32]; // Make sure our environment's sane if (builder && tcLabelText) { // Note our size at the stat lnStart = builder->populatedLength; // Label iBuilder_appendData(builder, tcLabelText, (s32)strlen(tcLabelText)); // Equals iBuilder_appendData(builder, " = ", 3); // Value sprintf(buffer, "%d\0", (s32)sdata); iBuilder_appendData(builder, buffer, (s32)strlen(buffer)); // CR/LF iBuilder_appendCrLf(builder); // Indicate how many bytes were written return(builder->populatedLength - lnStart); } else { // Failure return(0); } }
SDiskLock* iiDisk_lock_range(SThisCode* thisCode, SBuilder* lockRoot, s32 tnFile, s64 tnOffset, s32 tnLength, uptr tnExtra) { u32 lnI; SDiskLock* dl; ////////// // Iterate to find an empty slot ////// for (lnI = 0, dl = (SDiskLock*)lockRoot->buffer; lnI < lockRoot->populatedLength; lnI += sizeof(SDiskLock), dl++) { // Is this slot empty? if (!dl->isValid) break; // Yes } ////////// // When we get here, we have a slot or not ////// if (lnI >= lockRoot->populatedLength) { // Create a new one dl = (SDiskLock*)iBuilder_appendData(lockRoot, (cs8*)NULL, sizeof(SDiskLock)); // Note: disk members are all initialized to 0s } ////////// // Physically try the lock ////// dl->isValid = true; dl->nFile = tnFile; dl->nOffset = tnOffset; dl->nLength = 0; // Seek to the offset if (_lseeki64(tnFile, tnOffset, SEEK_SET) == tnOffset) { // Lock the bytes if (_locking(tnFile, _LK_NBLCK, tnLength) == 0) { // Indicate a successful lock dl->nLength = tnLength; } } else { // The length being 0 will indicate the lock failed // So we just let it fall through } ////////// // Indicate success or failure ////// return(dl); }
////////// // // Appends the indicated data to the end of the buffer. If the buffer is NULL, the // data is initialized to all 0s. This differs from iBuilder_appendBytes() which // does not do any initialization. // // Returns: // Pointer to the point in the buffer where the text was inserted, can be used // for a furthering or continuance of this function embedded in a higher call. ////// cs8* iBuilder_appendData(SBuilder* builder, SDatum* data) { // Make sure there's something to update if (builder && data && data->_data && data->length > 0) return((cs8*)iBuilder_appendData(builder, data->data_cu8, data->length)); // Return our original input return(NULL); }
////////// // // Called to create a pseudo device context // ////// SHdcX* iHwndX_createHdc(s32 tnWidth, s32 tnHeight, SBitmap* bmp) { union { uptr _hdc; SHdcX* hdc; }; ////////// // Make sure we have our HDC buffer allocated ////// if (!gsHdcs) iBuilder_createAndInitialize(&gsHdcs, -1); ////////// // Allocate a new one ////// hdc = (SHdcX*)iBuilder_appendData(gsHdcs, (s8*)NULL, sizeof(SHdcX)); if (hdc) { // Initialize hdc->isValid = true; hdc->hdc = _hdc; // Default settings hdc->isOpaque = false; hdc->colorFore.color = rgba(0,0,0,255); hdc->colorBack.color = rgba(255,255,255,255);; // Allocate the default font hdc->font = iFont_create(cgcFontName_default, 10, FW_NORMAL, 0, 0); // Allocate a bitmap if (!bmp) { // Create a bitmap hdc->bmp = iBmp_allocate(); iBmp_createBySize(hdc->bmp, tnWidth, tnHeight, 24); } else { // Use the indicated bitmap hdc->bmp = bmp; } } ////////// // Indicate success or failure ////// return(hdc); }
////////// // // Create a region for population // ////// SRegionX* iHwndX_createRegion(void) { ////////// // Make sure the array is valid ////// if (!gsRegions) iBuilder_createAndInitialize(&gsRegions, 1024); ////////// // Create a new region ////// return((SRegionX*)iBuilder_appendData(gsRegions, (s8*)NULL, sizeof(SRegionX))); }
////////// // // Obtain the next font that's available // ////// SFontX* iHwndX_getNextFont(void) { u32 lnI; SFontX* font; ////////// // Make sure the master list exists ////// if (!gsHfonts) iBuilder_createAndInitialize(&gsHfonts, -1); ////////// // Search for an empty slot ////// for (lnI = 0, font = (SFontX*)gsHfonts->buffer; lnI < gsHfonts->populatedLength; lnI += sizeof(SFontX), font++) { // If this one is not used, return it if (!font->isValid) break; } // If we get here, none were found ////////// // Allocate a new slot if need be ////// if (lnI >= gsHfonts->populatedLength) font = (SFontX*)iBuilder_appendData(gsHfonts, (s8*)NULL, sizeof(SFontX)); ////////// // Indicate success or failure ////// return(font); }
////////// // // Posts a message to the indicated win->msgQueue. // ////// bool iHwndX_postMessage_byWin(SHwndX* win, uptr message, uptr wParam, uptr lParam) { SMessageX* msg; // Make sure our environment is sane if (win && win->isValid) { ////////// // Make sure there's a message queue ////// if (!win->msgQueue) iBuilder_createAndInitialize(&win->msgQueue, -1); ////////// // Append the message ////// msg = (SMessageX*)iBuilder_appendData(win->msgQueue, (s8*)NULL, sizeof(SMessageX)); if (msg) { msg->msg.hwnd = win->hwnd; msg->msg.message = message; msg->msg.wParam = wParam; msg->msg.lParam = lParam; msg->msg.time = iHwndX_getTime(); memcpy(&msg->msg.pt, &win->mousePt, sizeof(msg->msg.pt)); // Indicate success return(true); } } // If we get here, failure return(false); }
////////// // // Top level lasm1 assembler // ////// int main(int argc, char* argv[]) { s32 lnI, lnErrors, lnWarnings, lnOrg, numread; bool llMap; SEM* asmFile; SBuilder* map; SLine* line; FILE* lfh; SOppie1Instruction* instr; s8 buffer[2048]; s8 output[2048]; ////////// // // SBsa bsa; // SOra ora; // SOrr orr; // // memset(&bsa, 0, sizeof(bsa)); // memset(&ora, 0, sizeof(ora)); // memset(&orr, 0, sizeof(orr)); // bsa.ooooo = 0x1f; // ora.ooo = 0x7; // orr.oooo = 0xf; // _asm nop; // ////// ////////// // Identify ourself ////// printf("LibSF Oppie-1 Assembler v0.02\n"); ////////// // Initialize Visual FreePro, Jr. stuff /////// InitializeCriticalSection(&cs_uniqueIdAccess); InitializeCriticalSection(&cs_logData); ////////// // lasm1 only takes one parameter, the input filename ////// if (argc < 2 || argc > 3) { // Display syntax printf("Usage: lasm1 myfile.asm /map\n"); } else { // Allocate our load manager asmFile = iSEM_allocate(true); if (!asmFile) { // Internal error printf("Internal error allocating load buffer\n"); } else { // Try to physically load it if (!iSEM_loadFromDisk(asmFile, argv[1], false, false)) { // Error opening printf("Unable to open %s\n", argv[1]); } else { // Indicate we're in progress printf("Assembling %s\n", argv[1]); // See if they specified /map llMap = (argc == 3 && strlen(argv[2]) == 4 && _memicmp(argv[2], "/map", 4) == 0); ////////// // Parse every line into known components ////// for (line = asmFile->firstLine; line; line = (SLine*)line->ll.next) iParseSourceCodeLine(line); ////////// // Compile every line that can be compiled, report any errors ////// for ( line = asmFile->firstLine, lnErrors = 0, lnWarnings = 0; line; line = (SLine*)line->ll.next ) { // Compile pass-1 if (line->compilerInfo->firstComp && line->compilerInfo->firstComp->iCode != _ICODE_COMMENT) iCompileSourceCodeLine(asmFile, line, &lnErrors, &lnWarnings, 1); } // If there were any errors, exit if (lnErrors != 0) exit_program(-1); ////////// // Assign addresses to everything ////// for ( lnOrg = 0, line = asmFile->firstLine; line; line = (SLine*)line->ll.next ) { ////////// // Based on the type update it ////// instr = (SOppie1Instruction*)line->compilerInfo->extra_info; if (instr->isOrg) { // Update the origin lnOrg = instr->org; } else { // Store the origin, and increase beyond this instruction's length instr->org = lnOrg; lnOrg += instr->size; } } ////////// // Compile every line which has an address that may not have been resolvable before ////// for ( line = asmFile->firstLine, lnErrors = 0, lnWarnings = 0; line; line = (SLine*)line->ll.next ) { // Compile pass-2 iCompileSourceCodeLine(asmFile, line, &lnErrors, &lnWarnings, 2); } // If there were any errors, exit if (lnErrors != 0) exit_program(-2); ////////// // When we get here, every line has compiled out. // Look for memory locations which will overlay ////// memset(output, 0, sizeof(output)); memset(buffer, 0, sizeof(buffer)); for ( line = asmFile->firstLine; line; line = (SLine*)line->ll.next ) { ////////// // Grab the instruction for this line ////// instr = (SOppie1Instruction*)line->compilerInfo->extra_info; if (instr->size != 0) { // There's some content there if (instr->isData) { ////////// // Store the data ////// for (lnI = 0; lnI < instr->size; lnI++) { // Increase our test buffer count ++buffer[instr->org + lnI]; if (buffer[instr->org + 1] > 1) { // We've overwritten a prior memory value printf("Addresses overlap on line %u\n", line->lineNumber); exit_program(-3); } // Copy the raw data output[instr->org + lnI] = instr->data[lnI]; } } else if (instr->isInstruction) { ////////// // Store the instruction ////// if (instr->org + instr->size - 1 >= 2048) { // It will wrap around the end printf("Invalid address for line %u\n", line->lineNumber); exit_program(-4); } ////////// // Increase for first byte ////// ++buffer[instr->org]; output[instr->org] = instr->ora.i_data1; if (buffer[instr->org] > 1) { // We've overwritten a prior memory value printf("Addresses overlap on line %u\n", line->lineNumber); exit_program(-5); } ////////// // If there's a second byte, do that one as well ////// if (instr->size == 2) { ++buffer[instr->org + 1]; output[instr->org + 1] = instr->ora.i_data2; if (buffer[instr->org + 1] > 1) { // We've overwritten a prior memory value printf("Addresses overlap on line %u\n", line->lineNumber); exit_program(-6); } } } } } ////////// // Create the otuput file ////// memcpy(argv[1] + strlen(argv[1]) - 4, ".img", 4); lfh = fopen(argv[1], "wb+"); if (!lfh) { // Could not create the output file printf("Error creating %s\n", argv[1]); exit_program(-7); } ////////// // Write the buffer ////// numread = fwrite(output, 1, 2048, lfh); fclose(lfh); if (numread != 2048) { printf("Error writing 2048 bytes\n"); exit_program(-8); } else { // Success printf("Wrote 2048 bytes\n"); } ////////// // They specified a map file ////// if (llMap) { ////////// // Allocate our output buffer ////// iBuilder_createAndInitialize(&map, -1); ////////// // Iterate through each line and convey data, or disassembly for the output ////// for ( line = asmFile->firstLine, lnErrors = 0, lnWarnings = 0; line; line = (SLine*)line->ll.next ) { ////////// // Grab the instruction for this line ////// instr = (SOppie1Instruction*)line->compilerInfo->extra_info; if (instr->size != 0) { ////////// // Show the address: ////// sprintf(buffer, "%03x: \0", instr->org); iBuilder_appendData(map, buffer, -1); ////////// // There's some content there ////// memset(buffer, 0, sizeof(buffer)); if (instr->isData) { ////////// // Show the data ////// for (lnI = 0; lnI < instr->size; lnI++) sprintf(buffer + (lnI * 3), "%02x%s", instr->data[lnI], ((lnI + 1 < instr->size) ? ",\0" : " \0")); } else if (instr->isInstruction) { // Disassemble the instruction iiDebo1_decodeAssembly(buffer, instr->org, false, true, (u8*)output); memset(buffer + strlen(buffer), 32, 64); buffer[45] = '/'; buffer[46] = '/'; memcpy(buffer + 48, line->sourceCode->data_s8, line->sourceCode_populatedLength); buffer[48 + line->sourceCode_populatedLength] = 0; } ////////// // Append the data ////// iBuilder_appendData(map, buffer, strlen(buffer)); iBuilder_appendCrLf(map); } } ////////// // Save the map file ////// memcpy(argv[1] + strlen(argv[1]) - 4, ".map", 4); iBuilder_asciiWriteOutFile(map, argv[1]); } } } } ////////// // Task completed (one way or another :-)) ////// exit_program(0); }
////////// // // Called to append a CR+LF to the builder // ////// u8* iBuilder_appendCrLf(SBuilder* builder) { return((u8*)iBuilder_appendData(builder, (cu8*)"\r\n", 2)); }
cs8* iBuilder_appendData(SBuilder* builder, cs8* tcData, u32 tnDataLength) { return((cs8*)iBuilder_appendData(builder, (cu8*)tcData, tnDataLength)); }